delete webtry from main skia repo; it's been moved to buildbots
BUG=skia: Review URL: https://codereview.chromium.org/688713002
This commit is contained in:
parent
7b3afa646e
commit
89154343f0
@ -1,286 +0,0 @@
|
||||
Design
|
||||
======
|
||||
|
||||
|
||||
Overview
|
||||
--------
|
||||
Allows trying out Skia code in the browser.
|
||||
|
||||
|
||||
Security
|
||||
--------
|
||||
|
||||
We're putting a C++ compiler on the web, and promising to run the results of
|
||||
user submitted code, so security is a large concern. Security is handled in a
|
||||
layered approach, using a combination of seccomp-bpf, chroot jail and rlimits.
|
||||
|
||||
*seccomp-bpf* - Used to limit the types of system calls that the user code can
|
||||
make. Any attempts to make a system call that isn't allowed causes the
|
||||
application to terminate immediately.
|
||||
|
||||
*chroot jail* - The code is run in a chroot jail, making the rest of the
|
||||
operating system files unreachable from the running code.
|
||||
|
||||
*rlimits* - Used to limit the resources the running code can get access to,
|
||||
for example runtime is limited to 5s of CPU.
|
||||
|
||||
User submitted code is also restricted in the following ways:
|
||||
* Limited to 10K of code total.
|
||||
* No preprocessor use is allowed (no lines can begin with #includes).
|
||||
|
||||
|
||||
Architecture
|
||||
------------
|
||||
|
||||
The server runs on GCE, and consists of a Go Web Server that calls out to the
|
||||
c++ compiler and executes code in a chroot jail. See the diagram below:
|
||||
|
||||
+–––––––––––––+
|
||||
| |
|
||||
| Browser |
|
||||
| |
|
||||
+––––––+––––––+
|
||||
|
|
||||
+––––––+––––––+
|
||||
| |
|
||||
| |
|
||||
| Web Server |
|
||||
| |
|
||||
| (Go) |
|
||||
| |
|
||||
| |
|
||||
+–––––––+–––––+
|
||||
|
|
||||
+–––––––+––––––––––+
|
||||
| chroot jail |
|
||||
| +––––––––––––––+|
|
||||
| | seccomp ||
|
||||
| | +––––––––––+||
|
||||
| | |User code |||
|
||||
| | | |||
|
||||
| | +––––––––––+||
|
||||
| +––––––––––––––+|
|
||||
| |
|
||||
+––––––––––––––––––+
|
||||
|
||||
The user code is expanded into a simple template and linked against libskia
|
||||
and a couple other .o files that contain main() and the code that sets up the
|
||||
seccomp and rlimit restrictions. This code also sets up the SkCanvas that is
|
||||
handed to the user code. Any code the user submits is restricted to running in
|
||||
a single function that looks like this:
|
||||
|
||||
|
||||
void draw(SkCanvas* canvas) {
|
||||
// User code goes here.
|
||||
}
|
||||
|
||||
The user code is tracked by taking an MD5 hash of the code The template is
|
||||
expanded out into <hash>.cpp, which is compiled into <hash>.o, which is then
|
||||
linked together with all the other libs and object files to create an
|
||||
executable named <hash>. That executable is copied into a directory
|
||||
/home/webtry/inout, that is accessible to both the web server and the schroot
|
||||
jail. The application is then run in the schroot jail, writing its response,
|
||||
<hash>.png, out into the same directory, /home/webtry/inout/, where is it read
|
||||
by the web server and returned to the user.
|
||||
|
||||
Startup and config
|
||||
------------------
|
||||
The server is started and stopped via:
|
||||
|
||||
sudo /etc/init.d/webtry [start|stop|restart]
|
||||
|
||||
But sysv init only handles starting and stopping a program once, so we use
|
||||
Monit to monitor the application and restart it if it crashes. The config
|
||||
is in:
|
||||
|
||||
/etc/monit/conf.d/webtry
|
||||
|
||||
The chroot jail is implemented using schroot, its configuration
|
||||
file is found in:
|
||||
|
||||
/etc/schroot/chroot.d/webtry
|
||||
|
||||
The seccomp configuration is in main.cpp and only allows the following system
|
||||
calls:
|
||||
|
||||
exit_group
|
||||
exit
|
||||
fstat
|
||||
read
|
||||
write
|
||||
close
|
||||
mmap
|
||||
munmap
|
||||
brk
|
||||
|
||||
Database
|
||||
--------
|
||||
|
||||
Code submitted is stored in an SQL database so that it can be referenced
|
||||
later, i.e. we can let users bookmark their SkFiddles.
|
||||
|
||||
The storage layer will be Cloud SQL (a cloud version of MySQL). Back of the
|
||||
envelope estimates of traffic come out to a price of a about $1/month.
|
||||
|
||||
All passwords for MySQL are stored in valentine.
|
||||
|
||||
To connect to the database from the skia-webtry-b server:
|
||||
|
||||
$ mysql --host=173.194.83.52 --user=root --password
|
||||
|
||||
Initial setup of the database, the user, and the tables:
|
||||
|
||||
CREATE DATABASE webtry;
|
||||
USE webtry;
|
||||
CREATE USER 'webtry'@'%' IDENTIFIED BY '<password is in valentine>';
|
||||
GRANT SELECT, INSERT, UPDATE ON webtry.webtry TO 'webtry'@'%';
|
||||
GRANT SELECT, INSERT, UPDATE ON webtry.workspace TO 'webtry'@'%';
|
||||
GRANT SELECT, INSERT, UPDATE ON webtry.workspacetry TO 'webtry'@'%';
|
||||
GRANT SELECT, INSERT, UPDATE ON webtry.source_images TO 'webtry'@'%';
|
||||
|
||||
// If this gets changed also update the sqlite create statement in webtry.go.
|
||||
|
||||
CREATE TABLE webtry (
|
||||
code TEXT DEFAULT '' NOT NULL,
|
||||
create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
hash CHAR(64) DEFAULT '' NOT NULL,
|
||||
width INTEGER DEFAULT 256 NOT NULL,
|
||||
height INTEGER DEFAULT 256 NOT NULL,
|
||||
source_image_id INTEGER DEFAULT 0 NOT NULL,
|
||||
PRIMARY KEY(hash),
|
||||
|
||||
FOREIGN KEY (source) REFERENCES sources(id)
|
||||
);
|
||||
|
||||
CREATE TABLE workspace (
|
||||
name CHAR(64) DEFAULT '' NOT NULL,
|
||||
create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
PRIMARY KEY(name),
|
||||
);
|
||||
|
||||
CREATE TABLE workspacetry (
|
||||
name CHAR(64) DEFAULT '' NOT NULL,
|
||||
create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
hash CHAR(64) DEFAULT '' NOT NULL,
|
||||
width INTEGER DEFAULT 256 NOT NULL,
|
||||
height INTEGER DEFAULT 256 NOT NULL,
|
||||
source_image_id INTEGER DEFAULT 0 NOT NULL,
|
||||
hidden INTEGER DEFAULT 0 NOT NULL,
|
||||
|
||||
FOREIGN KEY (name) REFERENCES workspace(name),
|
||||
);
|
||||
|
||||
CREATE TABLE source_images (
|
||||
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
|
||||
image MEDIUMBLOB DEFAULT '' NOT NULL, -- Stored as PNG.
|
||||
width INTEGER DEFAULT 0 NOT NULL,
|
||||
height INTEGER DEFAULT 0 NOT NULL,
|
||||
create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
hidden INTEGER DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE webtry ADD COLUMN source_image_id INTEGER DEFAULT 0 NOT NULL AFTER hash;
|
||||
ALTER TABLE workspacetry ADD COLUMN source_image_id INTEGER DEFAULT 0 NOT NULL AFTER hash;
|
||||
|
||||
Common queries webtry.go will use:
|
||||
|
||||
INSERT INTO webtry (code, hash) VALUES('int i = 0;...', 'abcdef...');
|
||||
|
||||
SELECT code, create_ts, hash FROM webtry WHERE hash='abcdef...';
|
||||
|
||||
SELECT code, create_ts, hash FROM webtry ORDER BY create_ts DESC LIMIT 2;
|
||||
|
||||
// To change the password for the webtry sql client:
|
||||
SET PASSWORD for 'webtry'@'%' = PASSWORD('<password is in valentine>');
|
||||
|
||||
// Run before and after to confirm the password changed:
|
||||
SELECT Host, User, Password FROM mysql.user;
|
||||
|
||||
Common queries for workspaces:
|
||||
|
||||
SELECT hash, create_ts FROM workspace ORDER BY create_ts DESC;
|
||||
|
||||
INSERT INTO workspace (name, hash) VALUES('autumn-river-12354', 'abcdef...');
|
||||
|
||||
SELECT name FROM workspace GROUP BY name;
|
||||
|
||||
Common queries for sources:
|
||||
|
||||
SELECT id, image, width, height, create_ts FROM source_images ORDER BY create_ts DESC LIMIT 100;
|
||||
|
||||
Password for the database will be stored in the metadata instance, if the
|
||||
metadata server can't be found, i.e. running locally, then a local sqlite
|
||||
database will be used. To see the current password stored in metadata and the
|
||||
fingerprint:
|
||||
|
||||
gcutil --project=google.com:skia-buildbots getinstance skia-webtry-b
|
||||
|
||||
To set the mysql password that webtry is to use:
|
||||
|
||||
gcutil --project=google.com:skia-buildbots setinstancemetadata skia-webtry-b --metadata=password:'[mysql client webtry password]' --fingerprint=[some fingerprint]
|
||||
|
||||
To retrieve the password from the running instance just GET the right URL from
|
||||
the metadata server:
|
||||
|
||||
curl "http://metadata/computeMetadata/v1/instance/attributes/password" -H "X-Google-Metadata-Request: True"
|
||||
|
||||
N.B. If you need to change the MySQL password that webtry uses, you must change
|
||||
it both in MySQL and the value stored in the metadata server.
|
||||
|
||||
Source Images
|
||||
-------------
|
||||
|
||||
For every try the user can select an optional source image to use as an input.
|
||||
The id of the source image is just an integer and is stored in the database
|
||||
along with the other try information, such as the code.
|
||||
|
||||
The actual image itself is also stored in a separate table, 'sources', in the
|
||||
database. On startup we check that all the images are available in 'inout',
|
||||
and write out the images if not. Since they are all written to 'inout' we can
|
||||
use the same /i/ image handler to serve them.
|
||||
|
||||
When a user uploads an image it is decoded and converted to PNG and stored
|
||||
as a binary blob in the database.
|
||||
|
||||
The bitmap is available to user code as a module level variable:
|
||||
|
||||
SkBitmap source;
|
||||
|
||||
The bitmap is read, decoded and stored in source before the seccomp jail is
|
||||
instantiated.
|
||||
|
||||
|
||||
Squid
|
||||
-----
|
||||
|
||||
Squid is configured to run on port 80 and run as an accelerator for the actual
|
||||
Go program which is running on port 8000. The config for the squid proxy is
|
||||
held in setup/sys/webtry_squid, which is copied into place during installation
|
||||
and squid is kept running via monit.
|
||||
|
||||
Workspaces
|
||||
----------
|
||||
|
||||
Workspaces are implemented by the workspace and workspacetry tables. The
|
||||
workspace table keeps the unique list of all workspaces. The workspacetry table
|
||||
keeps track of all the tries that have occured in a workspace. Right now the
|
||||
hidden column of workspacetry is not used, it's for future functionality.
|
||||
|
||||
Code Editor
|
||||
-----------
|
||||
[CodeMirror](http://codemirror.net/) is used for rich code editing. The
|
||||
following files are included from the official CodeMirror distribution and can
|
||||
be updated in place (no local customizations):
|
||||
|
||||
* codemirror.js - base CM implementation
|
||||
* codemirror.css - base CM stylesheet
|
||||
* clike.js - C-like syntax highlighting support
|
||||
|
||||
Alternatively, we may consider pulling CM as an external dependency at some
|
||||
point.
|
||||
|
||||
Installation
|
||||
------------
|
||||
See the README file.
|
||||
|
||||
|
@ -1,95 +0,0 @@
|
||||
WebTry Server
|
||||
=============
|
||||
|
||||
Allows trying out Skia code in the browser. Run a local webserver
|
||||
and from the pages it serves try out Skia code and see the results
|
||||
immediately.
|
||||
|
||||
|
||||
Running Locally
|
||||
===============
|
||||
|
||||
One time setup:
|
||||
|
||||
$ export SKIA_ROOT=path_to_your_skia_source
|
||||
$ export WEBTRY_INOUT=path_to_a_writeable_directory
|
||||
$ mkdir -p $WEBTRY_INOUT
|
||||
|
||||
Then, to run:
|
||||
|
||||
$ cd experimental/webtry
|
||||
$ go get -d
|
||||
$ ./build
|
||||
$ ./webtry
|
||||
|
||||
Then visit http://localhost:8000 in your browser.
|
||||
|
||||
Only tested under linux and MacOS, doubtful it will work on other platforms.
|
||||
|
||||
|
||||
Server Setup
|
||||
============
|
||||
|
||||
Create a GCE instance:
|
||||
|
||||
gcutil --project=google.com:skia-buildbots addinstance skia-webtry-b \
|
||||
--zone=us-central2-b --external_ip_address=108.170.220.126 \
|
||||
--service_account=default \
|
||||
--service_account_scopes="https://www.googleapis.com/auth/devstorage.full_control" \
|
||||
--network=default --machine_type=n1-standard-1 --image=backports-debian-7-wheezy-v20140331 \
|
||||
--persistent_boot_disk
|
||||
|
||||
Make sure port 80 is accessible externally for the above instance.
|
||||
|
||||
SSH into the instance:
|
||||
|
||||
gcutil --project=google.com:skia-buildbots ssh --ssh_user=default skia-webtry-b
|
||||
|
||||
|
||||
Do the first time
|
||||
=================
|
||||
|
||||
The following things only need to be done once.
|
||||
|
||||
1. SSH into the server as default.
|
||||
2. sudo apt-get install git
|
||||
3. git clone https://skia.googlesource.com/skia
|
||||
4. cd ~/skia/experimental/webtry/setup
|
||||
5. ./webtry_setup.sh
|
||||
|
||||
6. Add the following to the /etc/schroot/minimal/fstab:
|
||||
|
||||
none /run/shm tmpfs rw,nosuid,nodev,noexec 0 0
|
||||
/home/webtry/inout /skia_build/inout none rw,bind 0 0
|
||||
/home/webtry/cache /skia_build/cache none rw,bind 0 0
|
||||
|
||||
7. Change /etc/monit/monitrc to:
|
||||
|
||||
set daemon 2
|
||||
|
||||
then run the following so it applies:
|
||||
|
||||
sudo /etc/init.d/monit restart
|
||||
|
||||
This means that monit will poll every two seconds that our application is up and running.
|
||||
|
||||
8. Set the TCP keepalive. For more info see:
|
||||
https://developers.google.com/cloud-sql/docs/gce-access
|
||||
|
||||
sudo sh -c 'echo 60 > /proc/sys/net/ipv4/tcp_keepalive_time'
|
||||
|
||||
|
||||
To update the code
|
||||
==================
|
||||
|
||||
1. SSH into the server as default.
|
||||
2. cd ~/skia/experimental/webtry/setup
|
||||
3. git pull
|
||||
4. ./webtry_setup.sh
|
||||
|
||||
|
||||
Third Party Code
|
||||
================
|
||||
|
||||
* res/js/polyfill.js - Various JS polyfill libraries. To rebuild or update
|
||||
see poly/README.md.
|
@ -1,15 +0,0 @@
|
||||
Public facing feature requests
|
||||
------------------------------
|
||||
- versioning (which version of skia was this run against)
|
||||
- magnifying glass (both client side and server side)
|
||||
- specify scale, rotate, clip (possibly animating over a range)
|
||||
- change canvas size from 300x300 to other sizes
|
||||
|
||||
|
||||
Implementation details
|
||||
----------------------
|
||||
- Add flag for inout directory to webtry.go.
|
||||
- In webtry.go add mutexes per hash, to avoid conflicts of writing the same file at the same time.
|
||||
- Add font support in the c++ template.
|
||||
- Add inline links to doxygen.
|
||||
- Add monitoring and probing (nagios).
|
@ -1,30 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script builds the webtry server; before compilation we need to create the code template
|
||||
# so that it contains all publicly available header files in skia/include.
|
||||
#
|
||||
# By default, the script expects to be run out of the skia/experimental/webtry directory;
|
||||
# if we move directories around this can be overridden by setting the SKIA_ROOT and WEBTRY_ROOT
|
||||
# environment variables to point to the skia source tree and the webtry source tree,
|
||||
# respectively.
|
||||
|
||||
[ -z "$SKIA_ROOT" ] && SKIA_ROOT="../.."
|
||||
[ -z "$WEBTRY_ROOT" ] && WEBTRY_ROOT=`pwd`
|
||||
|
||||
[ -z "$GOROOT" ] && export GOROOT=/home/webtry/go
|
||||
[ -z "$GOPATH" ] && export GOPATH=/home/webtry/golib
|
||||
|
||||
PATH=$PATH:$GOROOT/bin
|
||||
|
||||
cd ${SKIA_ROOT}/include
|
||||
echo "Creating compile template..."
|
||||
find core effects pathops -maxdepth 1 -name "*.h" | sed "s/.*\///" | sed "s/\(.*\)/#include \"\1\"/" | sort > ${WEBTRY_ROOT}/templates/template.cpp
|
||||
echo '#include "sk_tool_utils.h"' >> ${WEBTRY_ROOT}/templates/template.cpp
|
||||
echo '#include "SkCommandLineFlags.h"' >> ${WEBTRY_ROOT}/templates/template.cpp
|
||||
echo '' >> ${WEBTRY_ROOT}/templates/template.cpp
|
||||
echo "SkBitmap source;" >> ${WEBTRY_ROOT}/templates/template.cpp
|
||||
echo "{{.Code}}" >> ${WEBTRY_ROOT}/templates/template.cpp
|
||||
cd ${WEBTRY_ROOT}
|
||||
echo "Building webtry..."
|
||||
go build webtry.go
|
||||
echo "Done!"
|
@ -1,43 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import os
|
||||
import sys
|
||||
|
||||
script_dir = os.path.dirname(__file__)
|
||||
|
||||
skia_src = os.path.abspath(os.environ.get('SKIA_SRC', os.path.join( script_dir, "..", "..")))
|
||||
gyp_source_dir = os.path.join(skia_src, 'third_party', 'externals', 'gyp')
|
||||
|
||||
WEBTRY_CACHE_DEFAULT = os.path.join(script_dir, "..", "..", "..", "cache")
|
||||
WEBTRY_INOUT_DEFAULT = os.path.join(script_dir, "..", "..", "..", "inout")
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(gyp_source_dir, 'pylib')))
|
||||
import gyp
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 2:
|
||||
print "Usage: gyp_for_webtry [code hash value]"
|
||||
sys.exit(-1)
|
||||
|
||||
args = sys.argv[2:]
|
||||
|
||||
if not os.environ.get('GYP_GENERATORS'):
|
||||
os.environ['GYP_GENERATORS'] = 'ninja'
|
||||
|
||||
args.append('--check')
|
||||
args.append('-I%s/gyp/common.gypi' % skia_src)
|
||||
args.extend(['--depth', '.'])
|
||||
webtry_cache_dir = os.path.abspath(os.environ.get('WEBTRY_CACHE', WEBTRY_CACHE_DEFAULT))
|
||||
webtry_inout_dir = os.path.abspath(os.environ.get('WEBTRY_INOUT', WEBTRY_INOUT_DEFAULT))
|
||||
|
||||
args.append('-Goutput_dir=%s' % webtry_inout_dir)
|
||||
|
||||
args.append(os.path.join(webtry_cache_dir, '%s.gyp' % sys.argv[1]))
|
||||
|
||||
# gyp is really picky about the current working directory having src/ under it
|
||||
os.chdir(webtry_cache_dir)
|
||||
|
||||
os.environ['CC'] = '../../skia/experimental/webtry/safec'
|
||||
os.environ['CXX'] = '../../skia/experimental/webtry/safec++'
|
||||
os.environ['LD'] = '../../skia/experimental/webtry/safec++'
|
||||
|
||||
sys.exit(gyp.main(args))
|
@ -1,208 +0,0 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "GrContextFactory.h"
|
||||
|
||||
#include "SkCanvas.h"
|
||||
#include "SkCommandLineFlags.h"
|
||||
#include "SkData.h"
|
||||
#include "SkForceLinking.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkImageDecoder.h"
|
||||
#include "SkImageEncoder.h"
|
||||
#include "SkImageInfo.h"
|
||||
#include "SkOSFile.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkSurface.h"
|
||||
|
||||
#include "seccomp_bpf.h"
|
||||
|
||||
__SK_FORCE_IMAGE_DECODER_LINKING;
|
||||
|
||||
DEFINE_string(out, "", "Output basename; fiddle will append the config used and the appropriate extension");
|
||||
DEFINE_string(source, "", "Filename of the source image.");
|
||||
DEFINE_int32(width, 256, "Width of output image.");
|
||||
DEFINE_int32(height, 256, "Height of output image.");
|
||||
DEFINE_bool(gpu, false, "Use GPU (Mesa) rendering.");
|
||||
DEFINE_bool(raster, true, "Use Raster rendering.");
|
||||
DEFINE_bool(pdf, false, "Use PDF rendering.");
|
||||
|
||||
// Defined in template.cpp.
|
||||
extern SkBitmap source;
|
||||
|
||||
static bool install_syscall_filter() {
|
||||
|
||||
#ifndef SK_UNSAFE_BUILD_DESKTOP_ONLY
|
||||
struct sock_filter filter[] = {
|
||||
/* Grab the system call number. */
|
||||
EXAMINE_SYSCALL,
|
||||
/* List allowed syscalls. */
|
||||
ALLOW_SYSCALL(exit_group),
|
||||
ALLOW_SYSCALL(exit),
|
||||
ALLOW_SYSCALL(fstat),
|
||||
ALLOW_SYSCALL(read),
|
||||
ALLOW_SYSCALL(write),
|
||||
ALLOW_SYSCALL(close),
|
||||
ALLOW_SYSCALL(mmap),
|
||||
ALLOW_SYSCALL(munmap),
|
||||
ALLOW_SYSCALL(brk),
|
||||
ALLOW_SYSCALL(futex),
|
||||
KILL_PROCESS,
|
||||
};
|
||||
struct sock_fprog prog = {
|
||||
SK_ARRAY_COUNT(filter),
|
||||
filter,
|
||||
};
|
||||
|
||||
// Lock down the app so that it can't get new privs, such as setuid.
|
||||
// Calling this is a requirement for an unpriviledged process to use mode
|
||||
// 2 seccomp filters, ala SECCOMP_MODE_FILTER, otherwise we'd have to be
|
||||
// root.
|
||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
|
||||
perror("prctl(NO_NEW_PRIVS)");
|
||||
goto failed;
|
||||
}
|
||||
// Now call seccomp and restrict the system calls that can be made to only
|
||||
// the ones in the provided filter list.
|
||||
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
|
||||
perror("prctl(SECCOMP)");
|
||||
goto failed;
|
||||
}
|
||||
return true;
|
||||
|
||||
failed:
|
||||
if (errno == EINVAL) {
|
||||
fprintf(stderr, "SECCOMP_FILTER is not available. :(\n");
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif /* SK_UNSAFE_BUILD_DESKTOP_ONLY */
|
||||
}
|
||||
|
||||
static void setLimits() {
|
||||
struct rlimit n;
|
||||
|
||||
// Limit to 5 seconds of CPU.
|
||||
n.rlim_cur = 5;
|
||||
n.rlim_max = 5;
|
||||
if (setrlimit(RLIMIT_CPU, &n)) {
|
||||
perror("setrlimit(RLIMIT_CPU)");
|
||||
}
|
||||
|
||||
// Limit to 150M of Address space.
|
||||
n.rlim_cur = 150000000;
|
||||
n.rlim_max = 150000000;
|
||||
if (setrlimit(RLIMIT_AS, &n)) {
|
||||
perror("setrlimit(RLIMIT_CPU)");
|
||||
}
|
||||
}
|
||||
|
||||
extern void draw(SkCanvas* canvas);
|
||||
|
||||
static void drawAndDump(SkSurface* surface, SkWStream* stream) {
|
||||
SkCanvas *canvas = surface->getCanvas();
|
||||
draw(canvas);
|
||||
|
||||
// Write out the image as a PNG.
|
||||
SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
|
||||
SkAutoTUnref<SkData> data(image->encode(SkImageEncoder::kPNG_Type, 100));
|
||||
if (NULL == data.get()) {
|
||||
printf("Failed to encode\n");
|
||||
exit(1);
|
||||
}
|
||||
stream->write(data->data(), data->size());
|
||||
}
|
||||
|
||||
static void drawRaster(SkWStream* stream, SkImageInfo info) {
|
||||
SkAutoTUnref<SkSurface> surface;
|
||||
surface.reset(SkSurface::NewRaster(info));
|
||||
drawAndDump(surface, stream);
|
||||
}
|
||||
|
||||
static void drawGPU(SkWStream* stream, GrContext* gr, SkImageInfo info) {
|
||||
SkAutoTUnref<SkSurface> surface;
|
||||
surface.reset(SkSurface::NewRenderTarget(gr,info));
|
||||
|
||||
drawAndDump(surface, stream);
|
||||
}
|
||||
|
||||
static void drawPDF(SkWStream* stream, SkImageInfo info) {
|
||||
printf( "Not implemented yet...\n");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
SkCommandLineFlags::Parse(argc, argv);
|
||||
SkAutoGraphics init;
|
||||
|
||||
if (FLAGS_out.count() == 0) {
|
||||
perror("The --out flag must have an argument.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (FLAGS_source.count() == 1) {
|
||||
const char *sourceDir = getenv("WEBTRY_INOUT");
|
||||
if (NULL == sourceDir) {
|
||||
sourceDir = "/skia_build/inout";
|
||||
}
|
||||
|
||||
SkString sourcePath = SkOSPath::Join(sourceDir, FLAGS_source[0]);
|
||||
if (!SkImageDecoder::DecodeFile(sourcePath.c_str(), &source)) {
|
||||
perror("Unable to read the source image.");
|
||||
}
|
||||
}
|
||||
|
||||
// make sure to open any needed output files before we set up the security
|
||||
// jail
|
||||
|
||||
SkWStream* streams[3] = {NULL, NULL, NULL};
|
||||
|
||||
if (FLAGS_raster) {
|
||||
SkString outPath;
|
||||
outPath.printf("%s_raster.png", FLAGS_out[0]);
|
||||
streams[0] = SkNEW_ARGS(SkFILEWStream,(outPath.c_str()));
|
||||
}
|
||||
if (FLAGS_gpu) {
|
||||
SkString outPath;
|
||||
outPath.printf("%s_gpu.png", FLAGS_out[0]);
|
||||
streams[1] = SkNEW_ARGS(SkFILEWStream,(outPath.c_str()));
|
||||
}
|
||||
if (FLAGS_pdf) {
|
||||
SkString outPath;
|
||||
outPath.printf("%s.pdf", FLAGS_out[0]);
|
||||
streams[2] = SkNEW_ARGS(SkFILEWStream,(outPath.c_str()));
|
||||
}
|
||||
|
||||
SkImageInfo info = SkImageInfo::MakeN32(FLAGS_width, FLAGS_height, kPremul_SkAlphaType);
|
||||
|
||||
GrContext *gr = NULL;
|
||||
GrContextFactory* grFactory = NULL;
|
||||
|
||||
// need to set up the GPU context before we install system call restrictions
|
||||
if (FLAGS_gpu) {
|
||||
|
||||
GrContext::Options grContextOpts;
|
||||
grFactory = new GrContextFactory(grContextOpts);
|
||||
gr = grFactory->get(GrContextFactory::kMESA_GLContextType);
|
||||
}
|
||||
|
||||
setLimits();
|
||||
|
||||
if (!install_syscall_filter()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (NULL != streams[0]) {
|
||||
drawRaster(streams[0], info);
|
||||
}
|
||||
if (NULL != streams[1]) {
|
||||
drawGPU(streams[1], gr, info);
|
||||
}
|
||||
if (NULL != streams[2]) {
|
||||
drawPDF(streams[2], info);
|
||||
}
|
||||
|
||||
if (gr) {
|
||||
delete grFactory;
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"directory": "../../../out/bower"
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
module.exports = function(grunt) {
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
// Install all the packages listed in the bower.json file.
|
||||
shell: {
|
||||
bower_install: {
|
||||
command: 'bower install'
|
||||
}
|
||||
},
|
||||
// Copy all the bower files into a single directory.
|
||||
bower: {
|
||||
dev: {
|
||||
dest: '../../../out/grunt/third_party'
|
||||
}
|
||||
},
|
||||
// Concatenate all the files in third_party into a single file.
|
||||
concat: {
|
||||
dist: {
|
||||
src: [
|
||||
'../../../out/grunt/third_party/WeakMap.js',
|
||||
'../../../out/grunt/third_party/classlist.js',
|
||||
'../../../out/grunt/third_party/pointerevents-polyfill.js',
|
||||
'../../../out/grunt/third_party/MutationObserver.js',
|
||||
'../../../out/grunt/third_party/CustomElements.js',
|
||||
'../../../out/grunt/third_party/HTMLImports.js',
|
||||
],
|
||||
dest: '../../../out/grunt/src/<%= pkg.name %>.js'
|
||||
}
|
||||
},
|
||||
// Uglify the one big file into one smaller file.
|
||||
uglify: {
|
||||
options: {
|
||||
banner: '/*! <%= pkg.name %> built from /exerimental/webtry/poly <%= grunt.template.today("yyyy-mm-dd") %> */\n'
|
||||
},
|
||||
build: {
|
||||
src: '../../../out/grunt/src/<%= pkg.name %>.js',
|
||||
dest: '../res/js/<%= pkg.name %>.js'
|
||||
}
|
||||
},
|
||||
copy: {
|
||||
simple: {
|
||||
src: '../../../out/grunt/src/<%= pkg.name %>.js',
|
||||
dest: '../res/js/<%= pkg.name %>.js'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Load the plugins for the above commands.
|
||||
grunt.loadNpmTasks('grunt-bower');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-contrib-cssmin');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-shell');
|
||||
|
||||
// By default run all the commands in the right sequence to build our custom minified polyfill.
|
||||
grunt.registerTask('default', ['shell:bower_install', 'bower', 'concat', 'uglify']);
|
||||
|
||||
// A target to build an unminified version, for debugging.
|
||||
grunt.registerTask('notmin', ['shell:bower_install', 'bower', 'concat', 'copy:simple']);
|
||||
|
||||
};
|
@ -1,17 +0,0 @@
|
||||
polyfill.js
|
||||
===========
|
||||
|
||||
To rebuild or update res/js/polyfill.js you will need to have
|
||||
[node.js](http://nodejs.org/) installed. Once you have it installed run the
|
||||
following (assuming you are in experimental/webtry directory):
|
||||
|
||||
$ cd poly
|
||||
$ npm install
|
||||
$ grunt
|
||||
|
||||
If you want to create a verion of the polyfill.js that hasn't been minified,
|
||||
say for debugging purposes, then run:
|
||||
|
||||
$ cd poly
|
||||
$ npm install
|
||||
$ grunt notmin
|
@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "polyfill",
|
||||
"version": "0.0.1",
|
||||
"authors": [
|
||||
"Joe Gregorio <jcgregorio@google.com>"
|
||||
],
|
||||
"description": "All the third party polyfills we use.",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"pointerevents-polyfill": "~0.2.0",
|
||||
"CustomElements": "~0.2.3",
|
||||
"HTMLImports": "~0.2.3"
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
"name": "polyfill",
|
||||
"version": "0.0.1",
|
||||
"description": "All the dependencies we need to run grunt and build our minified polyfill JS library.",
|
||||
"main": "polyfill.js",
|
||||
"author": "jcgregorio@google.com",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.5",
|
||||
"grunt-contrib-uglify": "~0.4.0",
|
||||
"grunt-bower": "~0.13.1",
|
||||
"grunt-contrib-concat": "~0.4.0",
|
||||
"grunt-shell": "~0.7.0",
|
||||
"grunt-contrib-copy": "~0.5.0",
|
||||
"grunt-contrib-cssmin": "~0.9.0"
|
||||
}
|
||||
}
|
@ -1,273 +0,0 @@
|
||||
/* BASICS */
|
||||
|
||||
.CodeMirror {
|
||||
/* Set height, width, borders, and global font properties here */
|
||||
font-family: monospace;
|
||||
}
|
||||
.CodeMirror-scroll {
|
||||
/* These settings combine to allow the code portion to automatically resize itself */
|
||||
height: auto;
|
||||
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
/* PADDING */
|
||||
|
||||
.CodeMirror-lines {
|
||||
padding: 4px 0; /* Vertical padding around content */
|
||||
}
|
||||
.CodeMirror pre {
|
||||
padding: 0 4px; /* Horizontal padding of content */
|
||||
}
|
||||
|
||||
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||
background-color: white; /* The little square between H and V scrollbars */
|
||||
}
|
||||
|
||||
/* GUTTER */
|
||||
|
||||
.CodeMirror-gutters {
|
||||
border-right: 1px solid #ddd;
|
||||
background-color: #f7f7f7;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.CodeMirror-linenumbers {}
|
||||
.CodeMirror-linenumber {
|
||||
padding: 0 3px 0 5px;
|
||||
min-width: 20px;
|
||||
text-align: right;
|
||||
color: #999;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/* CURSOR */
|
||||
|
||||
.CodeMirror div.CodeMirror-cursor {
|
||||
border-left: 1px solid black;
|
||||
}
|
||||
/* Shown when moving in bi-directional text */
|
||||
.CodeMirror div.CodeMirror-secondarycursor {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
|
||||
width: auto;
|
||||
border: 0;
|
||||
background: #7e7;
|
||||
}
|
||||
/* Can style cursor different in overwrite (non-insert) mode */
|
||||
div.CodeMirror-overwrite div.CodeMirror-cursor {}
|
||||
|
||||
.cm-tab { display: inline-block; }
|
||||
|
||||
.CodeMirror-ruler {
|
||||
border-left: 1px solid #ccc;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* DEFAULT THEME */
|
||||
|
||||
.cm-s-default .cm-keyword {color: #708;}
|
||||
.cm-s-default .cm-atom {color: #219;}
|
||||
.cm-s-default .cm-number {color: #164;}
|
||||
.cm-s-default .cm-def {color: #00f;}
|
||||
.cm-s-default .cm-variable,
|
||||
.cm-s-default .cm-punctuation,
|
||||
.cm-s-default .cm-property,
|
||||
.cm-s-default .cm-operator {}
|
||||
.cm-s-default .cm-variable-2 {color: #05a;}
|
||||
.cm-s-default .cm-variable-3 {color: #085;}
|
||||
.cm-s-default .cm-comment {color: #a50;}
|
||||
.cm-s-default .cm-string {color: #a11;}
|
||||
.cm-s-default .cm-string-2 {color: #f50;}
|
||||
.cm-s-default .cm-meta {color: #555;}
|
||||
.cm-s-default .cm-qualifier {color: #555;}
|
||||
.cm-s-default .cm-builtin {color: #30a;}
|
||||
.cm-s-default .cm-bracket {color: #997;}
|
||||
.cm-s-default .cm-tag {color: #170;}
|
||||
.cm-s-default .cm-attribute {color: #00c;}
|
||||
.cm-s-default .cm-header {color: blue;}
|
||||
.cm-s-default .cm-quote {color: #090;}
|
||||
.cm-s-default .cm-hr {color: #999;}
|
||||
.cm-s-default .cm-link {color: #00c;}
|
||||
|
||||
.cm-negative {color: #d44;}
|
||||
.cm-positive {color: #292;}
|
||||
.cm-header, .cm-strong {font-weight: bold;}
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-invalidchar {color: #f00;}
|
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
.CodeMirror-activeline-background {background: #e8f2ff;}
|
||||
|
||||
/* STOP */
|
||||
|
||||
/* The rest of this file contains styles related to the mechanics of
|
||||
the editor. You probably shouldn't touch them. */
|
||||
|
||||
.CodeMirror {
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||
/* See overflow: hidden in .CodeMirror */
|
||||
margin-bottom: -30px; margin-right: -30px;
|
||||
padding-bottom: 30px;
|
||||
outline: none; /* Prevent dragging from highlighting the element */
|
||||
position: relative;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
.CodeMirror-sizer {
|
||||
position: relative;
|
||||
border-right: 30px solid transparent;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||
before actuall scrolling happens, thus preventing shaking and
|
||||
flickering artifacts. */
|
||||
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
display: none;
|
||||
}
|
||||
.CodeMirror-vscrollbar {
|
||||
right: 0; top: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.CodeMirror-hscrollbar {
|
||||
bottom: 0; left: 0;
|
||||
overflow-y: hidden;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
.CodeMirror-scrollbar-filler {
|
||||
right: 0; bottom: 0;
|
||||
}
|
||||
.CodeMirror-gutter-filler {
|
||||
left: 0; bottom: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
position: absolute; left: 0; top: 0;
|
||||
padding-bottom: 30px;
|
||||
z-index: 3;
|
||||
}
|
||||
.CodeMirror-gutter {
|
||||
white-space: normal;
|
||||
height: 100%;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
padding-bottom: 30px;
|
||||
margin-bottom: -32px;
|
||||
display: inline-block;
|
||||
/* Hack to make IE7 behave */
|
||||
*zoom:1;
|
||||
*display:inline;
|
||||
}
|
||||
.CodeMirror-gutter-elt {
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.CodeMirror-lines {
|
||||
cursor: text;
|
||||
}
|
||||
.CodeMirror pre {
|
||||
/* Reset some styles that the rest of the page might have set */
|
||||
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
|
||||
border-width: 0;
|
||||
background: transparent;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
margin: 0;
|
||||
white-space: pre;
|
||||
word-wrap: normal;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
.CodeMirror-wrap pre {
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.CodeMirror-linebackground {
|
||||
position: absolute;
|
||||
left: 0; right: 0; top: 0; bottom: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-linewidget {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.CodeMirror-widget {}
|
||||
|
||||
.CodeMirror-wrap .CodeMirror-scroll {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-measure {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
.CodeMirror-measure pre { position: static; }
|
||||
|
||||
.CodeMirror div.CodeMirror-cursor {
|
||||
position: absolute;
|
||||
border-right: none;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
div.CodeMirror-cursors {
|
||||
visibility: hidden;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.CodeMirror-focused div.CodeMirror-cursors {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-selected { background: #d9d9d9; }
|
||||
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||
.CodeMirror-crosshair { cursor: crosshair; }
|
||||
|
||||
.cm-searching {
|
||||
background: #ffa;
|
||||
background: rgba(255, 255, 0, .4);
|
||||
}
|
||||
|
||||
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
|
||||
.CodeMirror span { *vertical-align: text-bottom; }
|
||||
|
||||
/* Used to force a border model for a node */
|
||||
.cm-force-border { padding-right: .1px; }
|
||||
|
||||
@media print {
|
||||
/* Hide the cursor when printing */
|
||||
.CodeMirror div.CodeMirror-cursors {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB |
@ -1,169 +0,0 @@
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
/**
|
||||
* A reusable HTML Import to enable zooming on images.
|
||||
*
|
||||
* To use, simply include this HTML Import and add the class 'zoom' to any
|
||||
* images you want zoomable.
|
||||
*
|
||||
* <link rel='import' type='text/html' href='/res/imp/zoom.html'>
|
||||
*
|
||||
* <img src="http://..." class="zoom"/>
|
||||
*
|
||||
* Any number of images on a page can be zoomable.
|
||||
*
|
||||
* If you want to display the rgb colors of the pixel at the center of the
|
||||
* zoom then add an id of 'zoomHex' to any element that supports
|
||||
* textContent, such as a div, p, span, etc.
|
||||
*
|
||||
* <p id=zoomHex></p>
|
||||
*
|
||||
* Note that HTML Imports need to be polyfilled in the near term.
|
||||
*/
|
||||
(function () {
|
||||
function onLoad() {
|
||||
var PIXELS = 20; // The number of pixels in width and height in a zoom.
|
||||
var clientX = 0;
|
||||
var clientY = 0;
|
||||
var lastClientX = 0;
|
||||
var lastClientY = 0;
|
||||
var ctx = null; // The 2D canvas context of the zoom.
|
||||
var currentImage = null; // The img node we are zooming for, otherwise null.
|
||||
var hex = document.getElementById('zoomHex');
|
||||
var canvasCopy = null;
|
||||
function zoomMove(e) {
|
||||
clientX = e.clientX;
|
||||
clientY = e.clientY;
|
||||
}
|
||||
function zoomMouseDown(e) {
|
||||
e.preventDefault();
|
||||
// Only do zooming on the primary mouse button.
|
||||
if (e.button != 0) {
|
||||
return
|
||||
}
|
||||
currentImage = e.target;
|
||||
clientX = e.clientX;
|
||||
clientY = e.clientY;
|
||||
lastClientX = clientX-1;
|
||||
lastClientY = clientY-1;
|
||||
document.body.style.cursor = 'crosshair';
|
||||
canvas = document.createElement('canvas');
|
||||
canvas.width = 1024;
|
||||
canvas.height = 1024;
|
||||
canvas.classList.add('zoomCanvas');
|
||||
ctx = canvas.getContext('2d');
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
this.parentNode.insertBefore(canvas, this);
|
||||
// Copy the image over to a canvas so we can read RGBA values for each point.
|
||||
if (hex) {
|
||||
canvasCopy = document.createElement('canvas');
|
||||
canvasCopy.width = currentImage.width;
|
||||
canvasCopy.height = currentImage.height;
|
||||
canvasCopy.id = 'zoomCopy';
|
||||
canvasCopy.getContext('2d').drawImage(currentImage, 0, 0, currentImage.width, currentImage.height);
|
||||
this.parentNode.insertBefore(canvasCopy, this);
|
||||
}
|
||||
document.body.addEventListener('pointermove', zoomMove, true);
|
||||
document.body.addEventListener('pointerup', zoomFinished);
|
||||
document.body.addEventListener('pointerleave', zoomFinished);
|
||||
// Kick off the drawing.
|
||||
setTimeout(drawZoom, 1);
|
||||
}
|
||||
function hexify(i) {
|
||||
var s = i.toString(16).toUpperCase();
|
||||
// Pad out to two hex digits if necessary.
|
||||
if (s.length < 2) {
|
||||
s = '0' + s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
function drawZoom() {
|
||||
if (currentImage) {
|
||||
// Only draw if the mouse has moved from the last time we drew.
|
||||
if (lastClientX != clientX || lastClientY != clientY) {
|
||||
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
var x = clientX - currentImage.x;
|
||||
var y = clientY - currentImage.y;
|
||||
var dx = Math.floor(ctx.canvas.width/PIXELS);
|
||||
var dy = Math.floor(ctx.canvas.height/PIXELS);
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeStyle = '#000';
|
||||
// Draw out each pixel as a rect on the target canvas, as this works around
|
||||
// FireFox doing a blur as it copies from one canvas to another.
|
||||
var colors = canvasCopy.getContext('2d').getImageData(x, y, PIXELS, PIXELS).data;
|
||||
for (var i=0; i<PIXELS; i++) {
|
||||
for (var j=0; j<PIXELS; j++) {
|
||||
var offset = (j*PIXELS+i)*4; // Offset into the colors array.
|
||||
ctx.fillStyle = 'rgba(' + colors[offset] + ', ' + colors[offset+1] + ', ' + colors[offset+2] + ', ' + colors[offset+3]/255.0 + ')';
|
||||
ctx.fillRect(i*dx, j*dy, dx-1, dy-1);
|
||||
// Box and label one selected pixel with its rgba values.
|
||||
if (hex && i==PIXELS/2 && j == PIXELS/2) {
|
||||
ctx.strokeRect(i*dx, j*dy, dx-1, dy-1);
|
||||
hex.textContent = 'rgba('
|
||||
+ colors[offset] + ', '
|
||||
+ colors[offset+1] + ', '
|
||||
+ colors[offset+2] + ', '
|
||||
+ colors[offset+3] + ') '
|
||||
+ hexify(colors[offset])
|
||||
+ hexify(colors[offset+1])
|
||||
+ hexify(colors[offset+2])
|
||||
+ hexify(colors[offset+3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
lastClientX = clientX;
|
||||
lastClientY = clientY;
|
||||
}
|
||||
setTimeout(drawZoom, 1000/30);
|
||||
}
|
||||
}
|
||||
function zoomFinished() {
|
||||
currentImage = null;
|
||||
if (hex) {
|
||||
hex.textContent = '';
|
||||
}
|
||||
document.body.style.cursor = 'default';
|
||||
ctx.canvas.parentNode.removeChild(ctx.canvas);
|
||||
canvasCopy.parentNode.removeChild(canvasCopy);
|
||||
document.body.removeEventListener('pointermove', zoomMove, true);
|
||||
document.body.removeEventListener('pointerup', zoomFinished);
|
||||
document.body.removeEventListener('pointerleave', zoomFinished);
|
||||
}
|
||||
|
||||
var zoomables = document.body.querySelectorAll('.zoom');
|
||||
for (var i=0; i<zoomables.length; i++) {
|
||||
zoomables[i].addEventListener('pointerdown', zoomMouseDown);
|
||||
}
|
||||
}
|
||||
|
||||
// If loaded via HTML Imports then DOMContentLoaded will be long done.
|
||||
if (document.readyState != "loading") {
|
||||
onLoad();
|
||||
} else {
|
||||
this.addEventListener('DOMContentLoaded', onLoad);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<style type="text/css" media="screen">
|
||||
.zoom {
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.zoomCanvas {
|
||||
position: absolute;
|
||||
width: vmin;
|
||||
height: vmin;
|
||||
top: 3em;
|
||||
right: 1em;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
#zoomCopy {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#zoomHex {
|
||||
text-shadow: 1px 1px #eee;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,436 +0,0 @@
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("clike", function(config, parserConfig) {
|
||||
var indentUnit = config.indentUnit,
|
||||
statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
|
||||
dontAlignCalls = parserConfig.dontAlignCalls,
|
||||
keywords = parserConfig.keywords || {},
|
||||
builtin = parserConfig.builtin || {},
|
||||
blockKeywords = parserConfig.blockKeywords || {},
|
||||
atoms = parserConfig.atoms || {},
|
||||
hooks = parserConfig.hooks || {},
|
||||
multiLineStrings = parserConfig.multiLineStrings;
|
||||
var isOperatorChar = /[+\-*&%=<>!?|\/]/;
|
||||
|
||||
var curPunc;
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
if (hooks[ch]) {
|
||||
var result = hooks[ch](stream, state);
|
||||
if (result !== false) return result;
|
||||
}
|
||||
if (ch == '"' || ch == "'") {
|
||||
state.tokenize = tokenString(ch);
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
|
||||
curPunc = ch;
|
||||
return null;
|
||||
}
|
||||
if (/\d/.test(ch)) {
|
||||
stream.eatWhile(/[\w\.]/);
|
||||
return "number";
|
||||
}
|
||||
if (ch == "/") {
|
||||
if (stream.eat("*")) {
|
||||
state.tokenize = tokenComment;
|
||||
return tokenComment(stream, state);
|
||||
}
|
||||
if (stream.eat("/")) {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
}
|
||||
if (isOperatorChar.test(ch)) {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
return "operator";
|
||||
}
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
var cur = stream.current();
|
||||
if (keywords.propertyIsEnumerable(cur)) {
|
||||
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
|
||||
return "keyword";
|
||||
}
|
||||
if (builtin.propertyIsEnumerable(cur)) {
|
||||
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
|
||||
return "builtin";
|
||||
}
|
||||
if (atoms.propertyIsEnumerable(cur)) return "atom";
|
||||
return "variable";
|
||||
}
|
||||
|
||||
function tokenString(quote) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, next, end = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == quote && !escaped) {end = true; break;}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
if (end || !(escaped || multiLineStrings))
|
||||
state.tokenize = null;
|
||||
return "string";
|
||||
};
|
||||
}
|
||||
|
||||
function tokenComment(stream, state) {
|
||||
var maybeEnd = false, ch;
|
||||
while (ch = stream.next()) {
|
||||
if (ch == "/" && maybeEnd) {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
maybeEnd = (ch == "*");
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
|
||||
function Context(indented, column, type, align, prev) {
|
||||
this.indented = indented;
|
||||
this.column = column;
|
||||
this.type = type;
|
||||
this.align = align;
|
||||
this.prev = prev;
|
||||
}
|
||||
function pushContext(state, col, type) {
|
||||
var indent = state.indented;
|
||||
if (state.context && state.context.type == "statement")
|
||||
indent = state.context.indented;
|
||||
return state.context = new Context(indent, col, type, null, state.context);
|
||||
}
|
||||
function popContext(state) {
|
||||
var t = state.context.type;
|
||||
if (t == ")" || t == "]" || t == "}")
|
||||
state.indented = state.context.indented;
|
||||
return state.context = state.context.prev;
|
||||
}
|
||||
|
||||
// Interface
|
||||
|
||||
return {
|
||||
startState: function(basecolumn) {
|
||||
return {
|
||||
tokenize: null,
|
||||
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
|
||||
indented: 0,
|
||||
startOfLine: true
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
var ctx = state.context;
|
||||
if (stream.sol()) {
|
||||
if (ctx.align == null) ctx.align = false;
|
||||
state.indented = stream.indentation();
|
||||
state.startOfLine = true;
|
||||
}
|
||||
if (stream.eatSpace()) return null;
|
||||
curPunc = null;
|
||||
var style = (state.tokenize || tokenBase)(stream, state);
|
||||
if (style == "comment" || style == "meta") return style;
|
||||
if (ctx.align == null) ctx.align = true;
|
||||
|
||||
if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
|
||||
else if (curPunc == "{") pushContext(state, stream.column(), "}");
|
||||
else if (curPunc == "[") pushContext(state, stream.column(), "]");
|
||||
else if (curPunc == "(") pushContext(state, stream.column(), ")");
|
||||
else if (curPunc == "}") {
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
if (ctx.type == "}") ctx = popContext(state);
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
}
|
||||
else if (curPunc == ctx.type) popContext(state);
|
||||
else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
|
||||
pushContext(state, stream.column(), "statement");
|
||||
state.startOfLine = false;
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
|
||||
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
|
||||
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
|
||||
var closing = firstChar == ctx.type;
|
||||
if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
|
||||
else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1);
|
||||
else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
|
||||
else return ctx.indented + (closing ? 0 : indentUnit);
|
||||
},
|
||||
|
||||
electricChars: "{}",
|
||||
blockCommentStart: "/*",
|
||||
blockCommentEnd: "*/",
|
||||
lineComment: "//",
|
||||
fold: "brace"
|
||||
};
|
||||
});
|
||||
|
||||
function words(str) {
|
||||
var obj = {}, words = str.split(" ");
|
||||
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
|
||||
"double static else struct entry switch extern typedef float union for unsigned " +
|
||||
"goto while enum void const signed volatile";
|
||||
|
||||
function cppHook(stream, state) {
|
||||
if (!state.startOfLine) return false;
|
||||
for (;;) {
|
||||
if (stream.skipTo("\\")) {
|
||||
stream.next();
|
||||
if (stream.eol()) {
|
||||
state.tokenize = cppHook;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
stream.skipToEnd();
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "meta";
|
||||
}
|
||||
|
||||
function cpp11StringHook(stream, state) {
|
||||
stream.backUp(1);
|
||||
// Raw strings.
|
||||
if (stream.match(/(R|u8R|uR|UR|LR)/)) {
|
||||
var match = stream.match(/"(.{0,16})\(/);
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
state.cpp11RawStringDelim = match[1];
|
||||
state.tokenize = tokenRawString;
|
||||
return tokenRawString(stream, state);
|
||||
}
|
||||
// Unicode strings/chars.
|
||||
if (stream.match(/(u8|u|U|L)/)) {
|
||||
if (stream.match(/["']/, /* eat */ false)) {
|
||||
return "string";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Ignore this hook.
|
||||
stream.next();
|
||||
return false;
|
||||
}
|
||||
|
||||
// C#-style strings where "" escapes a quote.
|
||||
function tokenAtString(stream, state) {
|
||||
var next;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == '"' && !stream.eat('"')) {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
// C++11 raw string literal is <prefix>"<delim>( anything )<delim>", where
|
||||
// <delim> can be a string up to 16 characters long.
|
||||
function tokenRawString(stream, state) {
|
||||
var closingSequence = new RegExp(".*?\\)" + state.cpp11RawStringDelim + '"');
|
||||
var match = stream.match(closingSequence);
|
||||
if (match) {
|
||||
state.tokenize = null;
|
||||
} else {
|
||||
stream.skipToEnd();
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
function def(mimes, mode) {
|
||||
if (typeof mimes == "string") mimes = [mimes];
|
||||
var words = [];
|
||||
function add(obj) {
|
||||
if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
|
||||
words.push(prop);
|
||||
}
|
||||
add(mode.keywords);
|
||||
add(mode.builtin);
|
||||
add(mode.atoms);
|
||||
if (words.length) {
|
||||
mode.helperType = mimes[0];
|
||||
CodeMirror.registerHelper("hintWords", mimes[0], words);
|
||||
}
|
||||
|
||||
for (var i = 0; i < mimes.length; ++i)
|
||||
CodeMirror.defineMIME(mimes[i], mode);
|
||||
}
|
||||
|
||||
def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords),
|
||||
blockKeywords: words("case do else for if switch while struct"),
|
||||
atoms: words("null"),
|
||||
hooks: {"#": cppHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def(["text/x-c++src", "text/x-c++hdr"], {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
|
||||
"static_cast typeid catch operator template typename class friend private " +
|
||||
"this using const_cast inline public throw virtual delete mutable protected " +
|
||||
"wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final " +
|
||||
"static_assert override"),
|
||||
blockKeywords: words("catch class do else finally for if struct switch try while"),
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"#": cppHook,
|
||||
"u": cpp11StringHook,
|
||||
"U": cpp11StringHook,
|
||||
"L": cpp11StringHook,
|
||||
"R": cpp11StringHook
|
||||
},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
def("text/x-java", {
|
||||
name: "clike",
|
||||
keywords: words("abstract assert boolean break byte case catch char class const continue default " +
|
||||
"do double else enum extends final finally float for goto if implements import " +
|
||||
"instanceof int interface long native new package private protected public " +
|
||||
"return short static strictfp super switch synchronized this throw throws transient " +
|
||||
"try void volatile while"),
|
||||
blockKeywords: words("catch class do else finally for if switch try while"),
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
}
|
||||
},
|
||||
modeProps: {fold: ["brace", "import"]}
|
||||
});
|
||||
def("text/x-csharp", {
|
||||
name: "clike",
|
||||
keywords: words("abstract as base break case catch checked class const continue" +
|
||||
" default delegate do else enum event explicit extern finally fixed for" +
|
||||
" foreach goto if implicit in interface internal is lock namespace new" +
|
||||
" operator out override params private protected public readonly ref return sealed" +
|
||||
" sizeof stackalloc static struct switch this throw try typeof unchecked" +
|
||||
" unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
|
||||
" global group into join let orderby partial remove select set value var yield"),
|
||||
blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
|
||||
builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
|
||||
" Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
|
||||
" UInt64 bool byte char decimal double short int long object" +
|
||||
" sbyte float string ushort uint ulong"),
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"@": function(stream, state) {
|
||||
if (stream.eat('"')) {
|
||||
state.tokenize = tokenAtString;
|
||||
return tokenAtString(stream, state);
|
||||
}
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
}
|
||||
}
|
||||
});
|
||||
def("text/x-scala", {
|
||||
name: "clike",
|
||||
keywords: words(
|
||||
|
||||
/* scala */
|
||||
"abstract case catch class def do else extends false final finally for forSome if " +
|
||||
"implicit import lazy match new null object override package private protected return " +
|
||||
"sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
|
||||
"<% >: # @ " +
|
||||
|
||||
/* package scala */
|
||||
"assert assume require print println printf readLine readBoolean readByte readShort " +
|
||||
"readChar readInt readLong readFloat readDouble " +
|
||||
|
||||
"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
|
||||
"Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
|
||||
"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
|
||||
"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
|
||||
"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
|
||||
|
||||
/* package java.lang */
|
||||
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
|
||||
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
|
||||
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
|
||||
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
|
||||
|
||||
|
||||
),
|
||||
blockKeywords: words("catch class do else finally for forSome if match switch try while"),
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
}
|
||||
}
|
||||
});
|
||||
def(["x-shader/x-vertex", "x-shader/x-fragment"], {
|
||||
name: "clike",
|
||||
keywords: words("float int bool void " +
|
||||
"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
|
||||
"mat2 mat3 mat4 " +
|
||||
"sampler1D sampler2D sampler3D samplerCube " +
|
||||
"sampler1DShadow sampler2DShadow" +
|
||||
"const attribute uniform varying " +
|
||||
"break continue discard return " +
|
||||
"for while do if else struct " +
|
||||
"in out inout"),
|
||||
blockKeywords: words("for while do if else struct"),
|
||||
builtin: words("radians degrees sin cos tan asin acos atan " +
|
||||
"pow exp log exp2 sqrt inversesqrt " +
|
||||
"abs sign floor ceil fract mod min max clamp mix step smootstep " +
|
||||
"length distance dot cross normalize ftransform faceforward " +
|
||||
"reflect refract matrixCompMult " +
|
||||
"lessThan lessThanEqual greaterThan greaterThanEqual " +
|
||||
"equal notEqual any all not " +
|
||||
"texture1D texture1DProj texture1DLod texture1DProjLod " +
|
||||
"texture2D texture2DProj texture2DLod texture2DProjLod " +
|
||||
"texture3D texture3DProj texture3DLod texture3DProjLod " +
|
||||
"textureCube textureCubeLod " +
|
||||
"shadow1D shadow2D shadow1DProj shadow2DProj " +
|
||||
"shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " +
|
||||
"dFdx dFdy fwidth " +
|
||||
"noise1 noise2 noise3 noise4"),
|
||||
atoms: words("true false " +
|
||||
"gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
|
||||
"gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
|
||||
"gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
|
||||
"gl_FogCoord " +
|
||||
"gl_Position gl_PointSize gl_ClipVertex " +
|
||||
"gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
|
||||
"gl_TexCoord gl_FogFragCoord " +
|
||||
"gl_FragCoord gl_FrontFacing " +
|
||||
"gl_FragColor gl_FragData gl_FragDepth " +
|
||||
"gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
|
||||
"gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
|
||||
"gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
|
||||
"gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
|
||||
"gl_ProjectionMatrixInverseTranspose " +
|
||||
"gl_ModelViewProjectionMatrixInverseTranspose " +
|
||||
"gl_TextureMatrixInverseTranspose " +
|
||||
"gl_NormalScale gl_DepthRange gl_ClipPlane " +
|
||||
"gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " +
|
||||
"gl_FrontLightModelProduct gl_BackLightModelProduct " +
|
||||
"gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " +
|
||||
"gl_FogParameters " +
|
||||
"gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " +
|
||||
"gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " +
|
||||
"gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
|
||||
"gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
|
||||
"gl_MaxDrawBuffers"),
|
||||
hooks: {"#": cppHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
});
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,430 +0,0 @@
|
||||
/**
|
||||
* Common JS that talks XHR back to the server and runs the code and receives
|
||||
* the results.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* All the functionality is wrapped up in this anonymous closure, but we need
|
||||
* to be told if we are on the workspace page or a normal try page, so the
|
||||
* workspaceName is passed into the closure, it must be set in the global
|
||||
* namespace. If workspaceName is the empty string then we know we aren't
|
||||
* running on a workspace page.
|
||||
*
|
||||
* If we are on a workspace page we also look for a 'history_'
|
||||
* variable in the global namespace which contains the list of tries
|
||||
* that are included in this workspace. That variable is used to
|
||||
* populate the history list.
|
||||
*/
|
||||
(function() {
|
||||
function onLoad() {
|
||||
var run = document.getElementById('run');
|
||||
var permalink = document.getElementById('permalink');
|
||||
var embed = document.getElementById('embed');
|
||||
var embedButton = document.getElementById('embedButton');
|
||||
var code = document.getElementById('code');
|
||||
var output = document.getElementById('output');
|
||||
var outputWrapper = document.getElementById('output-wrapper');
|
||||
var gpu = document.getElementById('use-gpu');
|
||||
var raster = document.getElementById('use-raster');
|
||||
var pdf = document.getElementById('use-pdf');
|
||||
var rasterOutput = document.getElementById('raster-output');
|
||||
var rasterImg = document.getElementById('raster-img');
|
||||
var gpuOutput = document.getElementById('gpu-output');
|
||||
var gpuImg = document.getElementById('gpu-img');
|
||||
var imageWidth = document.getElementById('image-width');
|
||||
var imageHeight = document.getElementById('image-height');
|
||||
var tryHistory = document.getElementById('tryHistory');
|
||||
var parser = new DOMParser();
|
||||
var tryTemplate = document.getElementById('tryTemplate');
|
||||
var sourcesTemplate = document.getElementById('sourcesTemplate');
|
||||
|
||||
var enableSource = document.getElementById('enableSource');
|
||||
var selectedSource = document.getElementById('selectedSource');
|
||||
var sourceCode = document.getElementById('sourceCode');
|
||||
var chooseSource = document.getElementById('chooseSource');
|
||||
var chooseList = document.getElementById('chooseList');
|
||||
|
||||
// Id of the source image to use, 0 if no source image is used.
|
||||
var sourceId = 0;
|
||||
|
||||
sourceId = parseInt(enableSource.getAttribute('data-id'));
|
||||
if (sourceId) {
|
||||
sourceSelectByID(sourceId);
|
||||
}
|
||||
|
||||
function setIFrameURL() {
|
||||
var url = document.URL;
|
||||
url = url.replace('/c/', '/iframe/');
|
||||
embed.value = '<iframe src="' + url + '" width="740" height="550" style="border: solid #00a 5px; border-radius: 5px;"/>'
|
||||
}
|
||||
|
||||
function beginWait() {
|
||||
document.body.classList.add('waiting');
|
||||
run.disabled = true;
|
||||
}
|
||||
|
||||
|
||||
function endWait() {
|
||||
document.body.classList.remove('waiting');
|
||||
run.disabled = false;
|
||||
}
|
||||
|
||||
|
||||
function sourceSelectByID(id) {
|
||||
sourceId = id;
|
||||
if (id > 0) {
|
||||
enableSource.checked = true;
|
||||
selectedSource.innerHTML = '<img with=64 height=64 src="/i/image-'+sourceId+'.png" />';
|
||||
selectedSource.classList.add('show');
|
||||
sourceCode.classList.add('show');
|
||||
chooseSource.classList.remove('show');
|
||||
} else {
|
||||
enableSource.checked = false;
|
||||
selectedSource.classList.remove('show');
|
||||
sourceCode.classList.remove('show');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A selection has been made in the choiceList.
|
||||
*/
|
||||
function sourceSelect() {
|
||||
sourceSelectByID(parseInt(this.getAttribute('data-id')));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback when the loading of the image sources is complete.
|
||||
*
|
||||
* Fills in the list of images from the data returned.
|
||||
*/
|
||||
function sourcesComplete(e) {
|
||||
endWait();
|
||||
// The response is JSON of the form:
|
||||
// [
|
||||
// {"id": 1},
|
||||
// {"id": 3},
|
||||
// ...
|
||||
// ]
|
||||
body = JSON.parse(e.target.response);
|
||||
// Clear out the old list if present.
|
||||
while (chooseList.firstChild) {
|
||||
chooseList.removeChild(chooseList.firstChild);
|
||||
}
|
||||
body.forEach(function(source) {
|
||||
var id = 'i'+source.id;
|
||||
var imgsrc = '/i/image-'+source.id+'.png';
|
||||
var clone = sourcesTemplate.content.cloneNode(true);
|
||||
clone.querySelector('img').src = imgsrc;
|
||||
clone.querySelector('button').setAttribute('id', id);
|
||||
clone.querySelector('button').setAttribute('data-id', source.id);
|
||||
chooseList.insertBefore(clone, chooseList.firstChild);
|
||||
chooseList.querySelector('#'+id).addEventListener('click', sourceSelect, true);
|
||||
});
|
||||
chooseSource.classList.add('show');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Toggle the use of a source image, or select a new source image.
|
||||
*
|
||||
* If enabling source images then load the list of available images via
|
||||
* XHR.
|
||||
*/
|
||||
function sourceClick(e) {
|
||||
selectedSource.classList.remove('show');
|
||||
sourceCode.classList.remove('show');
|
||||
if (enableSource.checked) {
|
||||
beginWait();
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', sourcesComplete);
|
||||
req.addEventListener('error', xhrError);
|
||||
req.overrideMimeType('application/json');
|
||||
req.open('GET', '/sources/', true);
|
||||
req.send();
|
||||
} else {
|
||||
sourceId = 0;
|
||||
chooseSource.classList.remove('show');
|
||||
}
|
||||
}
|
||||
|
||||
enableSource.addEventListener('click', sourceClick, true);
|
||||
selectedSource.addEventListener('click', sourceClick, true);
|
||||
|
||||
function configChange(e) {
|
||||
if (!(gpu.checked || raster.checked || pdf.checked)) {
|
||||
run.disabled = true;
|
||||
run.innerHTML = "Choose a configuration"
|
||||
} else {
|
||||
run.disabled = false;
|
||||
run.innerHTML = "Run"
|
||||
}
|
||||
}
|
||||
|
||||
gpu.addEventListener('change', configChange);
|
||||
raster.addEventListener('change', configChange);
|
||||
pdf.addEventListener('change', configChange);
|
||||
|
||||
|
||||
var editor = CodeMirror.fromTextArea(code, {
|
||||
theme: "default",
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
lineWrapping: true,
|
||||
mode: "text/x-c++src",
|
||||
indentUnit: 4,
|
||||
});
|
||||
|
||||
// Match the initial textarea width, but leave the height alone
|
||||
// The css will automatically resize the editor vertically.
|
||||
editor.setSize(editor.defaultCharWidth() * code.cols,
|
||||
null);
|
||||
|
||||
editor.on('beforeChange', function(instance, changeObj) {
|
||||
var startLine = changeObj.from.line;
|
||||
var endLine = changeObj.to.line;
|
||||
|
||||
for (var i = startLine ; i <= endLine ; i++) {
|
||||
editor.removeLineClass( i, "wrap", "error" );
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Callback when there's an XHR error.
|
||||
* @param e The callback event.
|
||||
*/
|
||||
function xhrError(e) {
|
||||
endWait();
|
||||
alert('Something bad happened: ' + e);
|
||||
}
|
||||
|
||||
function clearOutput() {
|
||||
output.textContent = "";
|
||||
outputWrapper.style.display='none';
|
||||
if (embed) {
|
||||
embed.style.display='none';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an image in the workspace history is clicked.
|
||||
*/
|
||||
function historyClick() {
|
||||
beginWait();
|
||||
clearOutput();
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', historyComplete);
|
||||
req.addEventListener('error', xhrError);
|
||||
req.overrideMimeType('application/json');
|
||||
req.open('GET', this.getAttribute('data-try'), true);
|
||||
req.send();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback for when the XHR kicked off in historyClick() returns.
|
||||
*/
|
||||
function historyComplete(e) {
|
||||
// The response is JSON of the form:
|
||||
// {
|
||||
// "hash": "unique id for a try",
|
||||
// "code": "source code for try"
|
||||
// }
|
||||
endWait();
|
||||
body = JSON.parse(e.target.response);
|
||||
code.value = body.code;
|
||||
editor.setValue(body.code);
|
||||
rasterImg.src = '/i/'+body.hash+'_raster.png';
|
||||
gpuImg.src = '/i/'+body.hash+'_gpu.png';
|
||||
imageWidth.value = body.width;
|
||||
imageHeight.value = body.height;
|
||||
gpu.checked = body.gpu;
|
||||
sourceSelectByID(body.source);
|
||||
if (permalink) {
|
||||
permalink.href = '/c/' + body.hash;
|
||||
permalink.style.display='inline-block';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the given try image to the history of a workspace.
|
||||
*/
|
||||
function addToHistory(hash, imgUrl) {
|
||||
var clone = tryTemplate.content.cloneNode(true);
|
||||
clone.querySelector('img').src = imgUrl;
|
||||
clone.querySelector('.tries').setAttribute('data-try', '/json/' + hash);
|
||||
tryHistory.insertBefore(clone, tryHistory.firstChild);
|
||||
tryHistory.querySelector('.tries').addEventListener('click', historyClick, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for when the user clicks on a compile error message
|
||||
*
|
||||
*/
|
||||
|
||||
function errorClick() {
|
||||
var line = this.getAttribute('data-line');
|
||||
var col = this.getAttribute('data-col');
|
||||
|
||||
editor.setCursor(line-1,col-1);
|
||||
editor.focus();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback for when the XHR returns after attempting to run the code.
|
||||
* @param e The callback event.
|
||||
*/
|
||||
function codeComplete(e) {
|
||||
// The response is JSON of the form:
|
||||
// {
|
||||
// "message": "you had an error...",
|
||||
// "img": "<base64 encoded image but only on success>"
|
||||
// }
|
||||
//
|
||||
// The img is optional and only appears if there is a valid
|
||||
// image to display.
|
||||
endWait();
|
||||
body = JSON.parse(e.target.response);
|
||||
if (null != body.compileErrors && body.compileErrors.length) {
|
||||
html = "";
|
||||
for (i = 0 ; i < body.compileErrors.length ; i++) {
|
||||
compileError = body.compileErrors[i];
|
||||
|
||||
err = document.createElement("div");
|
||||
err.className = "compile-error";
|
||||
|
||||
loc = document.createElement("span");
|
||||
loc.className = "error-location";
|
||||
loc.innerHTML = "Line " + compileError.line + ", col " + compileError.column + ": ";
|
||||
|
||||
errorMessage = document.createElement("span");
|
||||
errorMessage.className = "error-mesage";
|
||||
errorMessage.innerHTML = compileError.error;
|
||||
|
||||
err.appendChild(loc);
|
||||
err.appendChild(errorMessage);
|
||||
|
||||
err.setAttribute('data-line', compileError.line);
|
||||
err.setAttribute('data-col', compileError.column);
|
||||
|
||||
output.appendChild(err);
|
||||
|
||||
err.addEventListener('click', errorClick);
|
||||
|
||||
editor.addLineClass( parseInt( compileError.line ) - 1, "wrap", "error" );
|
||||
}
|
||||
outputWrapper.style.display = 'block';
|
||||
} else {
|
||||
output.textContent = body.message;
|
||||
if (body.message) {
|
||||
outputWrapper.style.display = 'block';
|
||||
}
|
||||
}
|
||||
if (body.hasOwnProperty('rasterImg') && body.rasterImg != "") {
|
||||
rasterImg.src = 'data:image/png;base64,' + body.rasterImg;
|
||||
rasterOutput.style.display = "inline-block";
|
||||
} else {
|
||||
rasterOutput.style.display = "none";
|
||||
rasterImg.src = '';
|
||||
}
|
||||
if (body.hasOwnProperty('gpuImg') && body.gpuImg != "") {
|
||||
gpuImg.src = 'data:image/png;base64,' + body.gpuImg;
|
||||
gpuOutput.style.display = "inline-block";
|
||||
} else {
|
||||
gpuImg.src = '';
|
||||
gpuOutput.style.display = "none";
|
||||
}
|
||||
// Add the image to the history if we are on a workspace page.
|
||||
if (tryHistory) {
|
||||
addToHistory(body.hash, 'data:image/png;base64,' + body.rasterImg);
|
||||
} else {
|
||||
window.history.pushState(null, null, '/c/' + body.hash);
|
||||
}
|
||||
if (permalink) {
|
||||
permalink.href = '/c/' + body.hash;
|
||||
permalink.style.display = 'inline-block';
|
||||
}
|
||||
if (embed) {
|
||||
setIFrameURL();
|
||||
}
|
||||
if (embedButton) {
|
||||
embedButton.style.display = 'inline-block';
|
||||
}
|
||||
}
|
||||
|
||||
function onSubmitCode() {
|
||||
beginWait();
|
||||
clearOutput();
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', codeComplete);
|
||||
req.addEventListener('error', xhrError);
|
||||
req.overrideMimeType('application/json');
|
||||
req.open('POST', '/', true);
|
||||
req.setRequestHeader('content-type', 'application/json');
|
||||
req.send(JSON.stringify({
|
||||
'code': editor.getValue(),
|
||||
'width': parseInt(imageWidth.value),
|
||||
'height': parseInt(imageHeight.value),
|
||||
'name': workspaceName,
|
||||
'source': sourceId,
|
||||
'gpu': gpu.checked,
|
||||
'raster': raster.checked,
|
||||
'pdf': pdf.checked
|
||||
}));
|
||||
}
|
||||
run.addEventListener('click', onSubmitCode);
|
||||
|
||||
|
||||
function onEmbedClick() {
|
||||
embed.style.display='inline';
|
||||
}
|
||||
|
||||
if (embedButton) {
|
||||
embedButton.addEventListener('click', onEmbedClick);
|
||||
}
|
||||
|
||||
setIFrameURL();
|
||||
|
||||
// Add the images to the history if we are on a workspace page.
|
||||
if (tryHistory && history_) {
|
||||
for (var i=0; i<history_.length; i++) {
|
||||
addToHistory(history_[i].hash, '/i/'+history_[i].hash+'.png');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If loaded via HTML Imports then DOMContentLoaded will be long done.
|
||||
if (document.readyState != "loading") {
|
||||
onLoad();
|
||||
} else {
|
||||
this.addEventListener('load', onLoad);
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
// TODO (humper) -- move the following functions out of the global
|
||||
// namespace as part of a web-components based fiddle frontend rewrite.
|
||||
|
||||
function collectionHas(a, b) { //helper function (see below)
|
||||
for(var i = 0, len = a.length; i < len; i ++) {
|
||||
if(a[i] == b) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function findParentBySelector(elm, selector) {
|
||||
var all = document.querySelectorAll(selector);
|
||||
var cur = elm.parentNode;
|
||||
while(cur && !collectionHas(all, cur)) { //keep going up until you find a match
|
||||
cur = cur.parentNode; //go up
|
||||
}
|
||||
return cur; //will return null if not found
|
||||
}
|
||||
|
||||
function onLoadImage(img) {
|
||||
var wrapper = findParentBySelector(img, ".image-wrapper");
|
||||
wrapper.style.display = "inline-block";
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
require 'compass/import-once/activate'
|
||||
require 'bootstrap-sass'
|
||||
# Require any additional compass plugins here.
|
||||
|
||||
# Set this to the root of your project when deployed:
|
||||
http_path = "/"
|
||||
css_dir = "css"
|
||||
sass_dir = "sass"
|
||||
images_dir = "img"
|
||||
javascripts_dir = "js"
|
||||
|
||||
# You can select your preferred output style here (can be overridden via the command line):
|
||||
# output_style = :expanded or :nested or :compact or :compressed
|
||||
|
||||
output_style = :compressed
|
||||
|
||||
# To enable relative paths to assets via compass helper functions. Uncomment:
|
||||
# relative_assets = true
|
||||
|
||||
# To disable debugging comments that display the original location of your selectors. Uncomment:
|
||||
# line_comments = false
|
||||
|
||||
|
||||
# If you prefer the indented syntax, you might want to regenerate this
|
||||
# project again passing --syntax sass, or you can uncomment this:
|
||||
# preferred_syntax = :sass
|
||||
# and then run:
|
||||
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
|
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.
@ -1,229 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata></metadata>
|
||||
<defs>
|
||||
<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
|
||||
<font-face units-per-em="1200" ascent="960" descent="-240" />
|
||||
<missing-glyph horiz-adv-x="500" />
|
||||
<glyph />
|
||||
<glyph />
|
||||
<glyph unicode="
" />
|
||||
<glyph unicode=" " />
|
||||
<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" />
|
||||
<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" />
|
||||
<glyph unicode=" " />
|
||||
<glyph unicode=" " horiz-adv-x="652" />
|
||||
<glyph unicode=" " horiz-adv-x="1304" />
|
||||
<glyph unicode=" " horiz-adv-x="652" />
|
||||
<glyph unicode=" " horiz-adv-x="1304" />
|
||||
<glyph unicode=" " horiz-adv-x="434" />
|
||||
<glyph unicode=" " horiz-adv-x="326" />
|
||||
<glyph unicode=" " horiz-adv-x="217" />
|
||||
<glyph unicode=" " horiz-adv-x="217" />
|
||||
<glyph unicode=" " horiz-adv-x="163" />
|
||||
<glyph unicode=" " horiz-adv-x="260" />
|
||||
<glyph unicode=" " horiz-adv-x="72" />
|
||||
<glyph unicode=" " horiz-adv-x="260" />
|
||||
<glyph unicode=" " horiz-adv-x="326" />
|
||||
<glyph unicode="€" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" />
|
||||
<glyph unicode="−" d="M200 400h900v300h-900v-300z" />
|
||||
<glyph unicode="◼" horiz-adv-x="500" d="M0 0z" />
|
||||
<glyph unicode="☁" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" />
|
||||
<glyph unicode="✉" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" />
|
||||
<glyph unicode="✏" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" />
|
||||
<glyph unicode="" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" />
|
||||
<glyph unicode="" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q18 -55 86 -75.5t147 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" />
|
||||
<glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" />
|
||||
<glyph unicode="" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" />
|
||||
<glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" />
|
||||
<glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" />
|
||||
<glyph unicode="" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" />
|
||||
<glyph unicode="" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" />
|
||||
<glyph unicode="" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" />
|
||||
<glyph unicode="" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" />
|
||||
<glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" />
|
||||
<glyph unicode="" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" />
|
||||
<glyph unicode="" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" />
|
||||
<glyph unicode="" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" />
|
||||
<glyph unicode="" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" />
|
||||
<glyph unicode="" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" />
|
||||
<glyph unicode="" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" />
|
||||
<glyph unicode="" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" />
|
||||
<glyph unicode="" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" />
|
||||
<glyph unicode="" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" />
|
||||
<glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" />
|
||||
<glyph unicode="" d="M0 25v475l200 700h800l199 -700l1 -475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" />
|
||||
<glyph unicode="" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" />
|
||||
<glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" />
|
||||
<glyph unicode="" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" />
|
||||
<glyph unicode="" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" />
|
||||
<glyph unicode="" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" />
|
||||
<glyph unicode="" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" />
|
||||
<glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" />
|
||||
<glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" />
|
||||
<glyph unicode="" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" />
|
||||
<glyph unicode="" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" />
|
||||
<glyph unicode="" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" />
|
||||
<glyph unicode="" d="M0 700l1 475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" />
|
||||
<glyph unicode="" d="M1 700l1 475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" />
|
||||
<glyph unicode="" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" />
|
||||
<glyph unicode="" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" />
|
||||
<glyph unicode="" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" />
|
||||
<glyph unicode="" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" />
|
||||
<glyph unicode="" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" />
|
||||
<glyph unicode="" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v71l471 -1q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" />
|
||||
<glyph unicode="" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" />
|
||||
<glyph unicode="" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " />
|
||||
<glyph unicode="" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" />
|
||||
<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
|
||||
<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
|
||||
<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" />
|
||||
<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" />
|
||||
<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" />
|
||||
<glyph unicode="" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" />
|
||||
<glyph unicode="" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" />
|
||||
<glyph unicode="" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" />
|
||||
<glyph unicode="" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " />
|
||||
<glyph unicode="" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" />
|
||||
<glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" />
|
||||
<glyph unicode="" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 139t-64 210zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" />
|
||||
<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" />
|
||||
<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" />
|
||||
<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q61 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l567 567l-137 137l-430 -431l-146 147z" />
|
||||
<glyph unicode="" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" />
|
||||
<glyph unicode="" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
|
||||
<glyph unicode="" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" />
|
||||
<glyph unicode="" d="M200 0l900 550l-900 550v-1100z" />
|
||||
<glyph unicode="" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
|
||||
<glyph unicode="" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
|
||||
<glyph unicode="" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" />
|
||||
<glyph unicode="" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" />
|
||||
<glyph unicode="" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" />
|
||||
<glyph unicode="" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" />
|
||||
<glyph unicode="" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" />
|
||||
<glyph unicode="" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h600v200h-600v-200z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141 z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM364 700h143q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5 q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-50 0 -90.5 -12t-75 -38.5t-53.5 -74.5t-19 -114zM500 300h200v100h-200 v-100z" />
|
||||
<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" />
|
||||
<glyph unicode="" d="M0 500v200h195q31 125 98.5 199.5t206.5 100.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200v-206 q149 48 201 206h-201v200h200q-25 74 -75.5 127t-124.5 77v-204h-200v203q-75 -23 -130 -77t-79 -126h209v-200h-210z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" />
|
||||
<glyph unicode="" d="M0 547l600 453v-300h600v-300h-600v-301z" />
|
||||
<glyph unicode="" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" />
|
||||
<glyph unicode="" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" />
|
||||
<glyph unicode="" d="M104 600h296v600h300v-600h298l-449 -600z" />
|
||||
<glyph unicode="" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" />
|
||||
<glyph unicode="" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" />
|
||||
<glyph unicode="" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" />
|
||||
<glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5h-207q-21 0 -33 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" />
|
||||
<glyph unicode="" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111q1 1 1 6.5t-1.5 15t-3.5 17.5l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6 h-111v-100zM100 0h400v400h-400v-400zM200 900q-3 0 14 48t36 96l18 47l213 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" />
|
||||
<glyph unicode="" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" />
|
||||
<glyph unicode="" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" />
|
||||
<glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" />
|
||||
<glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" />
|
||||
<glyph unicode="" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 34 -48 36.5t-48 -29.5l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" />
|
||||
<glyph unicode="" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -20 -13 -28.5t-32 0.5l-94 78h-222l-94 -78q-19 -9 -32 -0.5t-13 28.5 v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" />
|
||||
<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" />
|
||||
<glyph unicode="" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" />
|
||||
<glyph unicode="" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" />
|
||||
<glyph unicode="" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" />
|
||||
<glyph unicode="" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" />
|
||||
<glyph unicode="" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" />
|
||||
<glyph unicode="" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" />
|
||||
<glyph unicode="" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" />
|
||||
<glyph unicode="" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" />
|
||||
<glyph unicode="" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" />
|
||||
<glyph unicode="" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" />
|
||||
<glyph unicode="" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" />
|
||||
<glyph unicode="" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" />
|
||||
<glyph unicode="" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM100 500v250v8v8v7t0.5 7t1.5 5.5t2 5t3 4t4.5 3.5t6 1.5t7.5 0.5h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35 q-55 337 -55 351zM1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" />
|
||||
<glyph unicode="" d="M74 350q0 21 13.5 35.5t33.5 14.5h18l117 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5q-18 -36 -18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-8 -3 -23 -8.5 t-65 -20t-103 -25t-132.5 -19.5t-158.5 -9q-125 0 -245.5 20.5t-178.5 40.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" />
|
||||
<glyph unicode="" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" />
|
||||
<glyph unicode="" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q124 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 213l100 212h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" />
|
||||
<glyph unicode="" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q124 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" />
|
||||
<glyph unicode="" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" />
|
||||
<glyph unicode="" d="M-101 651q0 72 54 110t139 38l302 -1l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 17 -10.5t26.5 -26t16.5 -36.5v-526q0 -13 -86 -93.5t-94 -80.5h-341q-16 0 -29.5 20t-19.5 41l-130 339h-107q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l107 89v502l-343 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM1000 201v600h200v-600h-200z" />
|
||||
<glyph unicode="" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6.5v7.5v6.5v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" />
|
||||
<glyph unicode="" d="M2 585q-16 -31 6 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85q0 -51 -0.5 -153.5t-0.5 -148.5q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM77 565l236 339h503 l89 -100v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" />
|
||||
<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM298 701l2 -201h300l-2 -194l402 294l-402 298v-197h-300z" />
|
||||
<glyph unicode="" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l402 -294l-2 194h300l2 201h-300v197z" />
|
||||
<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" />
|
||||
<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" />
|
||||
<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60 q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q104 -3 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5 t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5 q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 39 2 44q31 -13 58 -14.5t39 3.5l11 4q7 36 -16.5 53.5t-64.5 28.5t-56 23q-19 -3 -37 0 q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5zM518 916q3 12 16 30t16 25q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -24 17 -66.5t17 -43.5 q-9 2 -31 5t-36 5t-32 8t-30 14zM692 1003h1h-1z" />
|
||||
<glyph unicode="" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" />
|
||||
<glyph unicode="" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" />
|
||||
<glyph unicode="" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" />
|
||||
<glyph unicode="" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" />
|
||||
<glyph unicode="" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM514 609q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" />
|
||||
<glyph unicode="" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -78.5 -16.5t-67.5 -51.5l-389 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23 q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60 l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" />
|
||||
<glyph unicode="" d="M80 784q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100q-71 70 -104.5 105.5t-77 89.5t-61 99 t-17.5 91zM250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-105 48.5q-74 0 -132 -83l-118 -171l-114 174q-51 80 -123 80q-60 0 -109.5 -49.5t-49.5 -118.5z" />
|
||||
<glyph unicode="" d="M57 353q0 -95 66 -159l141 -142q68 -66 159 -66q93 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-8 9 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141q7 -7 19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -17q47 -49 77 -100l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" />
|
||||
<glyph unicode="" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" />
|
||||
<glyph unicode="" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" />
|
||||
<glyph unicode="" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335q-6 1 -15.5 4t-11.5 3q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5 v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5 zM700 237q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" />
|
||||
<glyph unicode="" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -28 16.5 -69.5t28 -62.5t41.5 -72h241v-100h-197q8 -50 -2.5 -115 t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q33 1 103 -16t103 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221z" />
|
||||
<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" />
|
||||
<glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" />
|
||||
<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" />
|
||||
<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" />
|
||||
<glyph unicode="" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" />
|
||||
<glyph unicode="" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" />
|
||||
<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" />
|
||||
<glyph unicode="" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" />
|
||||
<glyph unicode="" d="M217 519q8 -19 31 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8h9q14 0 26 15q11 13 274.5 321.5t264.5 308.5q14 19 5 36q-8 17 -31 17l-301 -1q1 4 78 219.5t79 227.5q2 15 -5 27l-9 9h-9q-15 0 -25 -16q-4 -6 -98 -111.5t-228.5 -257t-209.5 -237.5q-16 -19 -6 -41 z" />
|
||||
<glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " />
|
||||
<glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" />
|
||||
<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" />
|
||||
<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" />
|
||||
<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" />
|
||||
<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 400l697 1l3 699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" />
|
||||
<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l249 -237l-1 697zM900 150h100v50h-100v-50z" />
|
||||
<glyph unicode="" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" />
|
||||
<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" />
|
||||
<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" />
|
||||
<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" />
|
||||
<glyph unicode="" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" />
|
||||
<glyph unicode="" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" />
|
||||
<glyph unicode="" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -116q-25 -17 -43.5 -51.5t-18.5 -65.5v-359z" />
|
||||
<glyph unicode="" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" />
|
||||
<glyph unicode="" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" />
|
||||
<glyph unicode="" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q17 18 13.5 41t-22.5 37l-192 136q-19 14 -45 12t-42 -19l-118 -118q-142 101 -268 227t-227 268l118 118q17 17 20 41.5t-11 44.5 l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" />
|
||||
<glyph unicode="" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-20 0 -35 14.5t-15 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" />
|
||||
<glyph unicode="" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" />
|
||||
<glyph unicode="" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
|
||||
<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" />
|
||||
<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" />
|
||||
<glyph unicode="" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" />
|
||||
<glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300h200 l-300 -300z" />
|
||||
<glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104.5t60.5 178.5q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" />
|
||||
<glyph unicode="" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" />
|
||||
<glyph unicode="" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" />
|
||||
</font>
|
||||
</defs></svg>
|
Before Width: | Height: | Size: 62 KiB |
Binary file not shown.
Binary file not shown.
@ -1,12 +0,0 @@
|
||||
//= require ./bootstrap/affix
|
||||
//= require ./bootstrap/alert
|
||||
//= require ./bootstrap/button
|
||||
//= require ./bootstrap/carousel
|
||||
//= require ./bootstrap/collapse
|
||||
//= require ./bootstrap/dropdown
|
||||
//= require ./bootstrap/tab
|
||||
//= require ./bootstrap/transition
|
||||
//= require ./bootstrap/scrollspy
|
||||
//= require ./bootstrap/modal
|
||||
//= require ./bootstrap/tooltip
|
||||
//= require ./bootstrap/popover
|
2107
experimental/webtry/res/webtry/js/bootstrap.js
vendored
2107
experimental/webtry/res/webtry/js/bootstrap.js
vendored
File diff suppressed because it is too large
Load Diff
@ -1,142 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: affix.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#affix
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// AFFIX CLASS DEFINITION
|
||||
// ======================
|
||||
|
||||
var Affix = function (element, options) {
|
||||
this.options = $.extend({}, Affix.DEFAULTS, options)
|
||||
|
||||
this.$target = $(this.options.target)
|
||||
.on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
|
||||
.on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
|
||||
|
||||
this.$element = $(element)
|
||||
this.affixed =
|
||||
this.unpin =
|
||||
this.pinnedOffset = null
|
||||
|
||||
this.checkPosition()
|
||||
}
|
||||
|
||||
Affix.VERSION = '3.2.0'
|
||||
|
||||
Affix.RESET = 'affix affix-top affix-bottom'
|
||||
|
||||
Affix.DEFAULTS = {
|
||||
offset: 0,
|
||||
target: window
|
||||
}
|
||||
|
||||
Affix.prototype.getPinnedOffset = function () {
|
||||
if (this.pinnedOffset) return this.pinnedOffset
|
||||
this.$element.removeClass(Affix.RESET).addClass('affix')
|
||||
var scrollTop = this.$target.scrollTop()
|
||||
var position = this.$element.offset()
|
||||
return (this.pinnedOffset = position.top - scrollTop)
|
||||
}
|
||||
|
||||
Affix.prototype.checkPositionWithEventLoop = function () {
|
||||
setTimeout($.proxy(this.checkPosition, this), 1)
|
||||
}
|
||||
|
||||
Affix.prototype.checkPosition = function () {
|
||||
if (!this.$element.is(':visible')) return
|
||||
|
||||
var scrollHeight = $(document).height()
|
||||
var scrollTop = this.$target.scrollTop()
|
||||
var position = this.$element.offset()
|
||||
var offset = this.options.offset
|
||||
var offsetTop = offset.top
|
||||
var offsetBottom = offset.bottom
|
||||
|
||||
if (typeof offset != 'object') offsetBottom = offsetTop = offset
|
||||
if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
|
||||
if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
|
||||
|
||||
var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false :
|
||||
offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
|
||||
offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false
|
||||
|
||||
if (this.affixed === affix) return
|
||||
if (this.unpin != null) this.$element.css('top', '')
|
||||
|
||||
var affixType = 'affix' + (affix ? '-' + affix : '')
|
||||
var e = $.Event(affixType + '.bs.affix')
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
this.affixed = affix
|
||||
this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
|
||||
|
||||
this.$element
|
||||
.removeClass(Affix.RESET)
|
||||
.addClass(affixType)
|
||||
.trigger($.Event(affixType.replace('affix', 'affixed')))
|
||||
|
||||
if (affix == 'bottom') {
|
||||
this.$element.offset({
|
||||
top: scrollHeight - this.$element.height() - offsetBottom
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// AFFIX PLUGIN DEFINITION
|
||||
// =======================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.affix')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.affix
|
||||
|
||||
$.fn.affix = Plugin
|
||||
$.fn.affix.Constructor = Affix
|
||||
|
||||
|
||||
// AFFIX NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.affix.noConflict = function () {
|
||||
$.fn.affix = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// AFFIX DATA-API
|
||||
// ==============
|
||||
|
||||
$(window).on('load', function () {
|
||||
$('[data-spy="affix"]').each(function () {
|
||||
var $spy = $(this)
|
||||
var data = $spy.data()
|
||||
|
||||
data.offset = data.offset || {}
|
||||
|
||||
if (data.offsetBottom) data.offset.bottom = data.offsetBottom
|
||||
if (data.offsetTop) data.offset.top = data.offsetTop
|
||||
|
||||
Plugin.call($spy, data)
|
||||
})
|
||||
})
|
||||
|
||||
}(jQuery);
|
@ -1,92 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: alert.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#alerts
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// ALERT CLASS DEFINITION
|
||||
// ======================
|
||||
|
||||
var dismiss = '[data-dismiss="alert"]'
|
||||
var Alert = function (el) {
|
||||
$(el).on('click', dismiss, this.close)
|
||||
}
|
||||
|
||||
Alert.VERSION = '3.2.0'
|
||||
|
||||
Alert.prototype.close = function (e) {
|
||||
var $this = $(this)
|
||||
var selector = $this.attr('data-target')
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
|
||||
}
|
||||
|
||||
var $parent = $(selector)
|
||||
|
||||
if (e) e.preventDefault()
|
||||
|
||||
if (!$parent.length) {
|
||||
$parent = $this.hasClass('alert') ? $this : $this.parent()
|
||||
}
|
||||
|
||||
$parent.trigger(e = $.Event('close.bs.alert'))
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
$parent.removeClass('in')
|
||||
|
||||
function removeElement() {
|
||||
// detach from parent, fire event then clean up data
|
||||
$parent.detach().trigger('closed.bs.alert').remove()
|
||||
}
|
||||
|
||||
$.support.transition && $parent.hasClass('fade') ?
|
||||
$parent
|
||||
.one('bsTransitionEnd', removeElement)
|
||||
.emulateTransitionEnd(150) :
|
||||
removeElement()
|
||||
}
|
||||
|
||||
|
||||
// ALERT PLUGIN DEFINITION
|
||||
// =======================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.alert')
|
||||
|
||||
if (!data) $this.data('bs.alert', (data = new Alert(this)))
|
||||
if (typeof option == 'string') data[option].call($this)
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.alert
|
||||
|
||||
$.fn.alert = Plugin
|
||||
$.fn.alert.Constructor = Alert
|
||||
|
||||
|
||||
// ALERT NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.alert.noConflict = function () {
|
||||
$.fn.alert = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// ALERT DATA-API
|
||||
// ==============
|
||||
|
||||
$(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
|
||||
|
||||
}(jQuery);
|
@ -1,110 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: button.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#buttons
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// BUTTON PUBLIC CLASS DEFINITION
|
||||
// ==============================
|
||||
|
||||
var Button = function (element, options) {
|
||||
this.$element = $(element)
|
||||
this.options = $.extend({}, Button.DEFAULTS, options)
|
||||
this.isLoading = false
|
||||
}
|
||||
|
||||
Button.VERSION = '3.2.0'
|
||||
|
||||
Button.DEFAULTS = {
|
||||
loadingText: 'loading...'
|
||||
}
|
||||
|
||||
Button.prototype.setState = function (state) {
|
||||
var d = 'disabled'
|
||||
var $el = this.$element
|
||||
var val = $el.is('input') ? 'val' : 'html'
|
||||
var data = $el.data()
|
||||
|
||||
state = state + 'Text'
|
||||
|
||||
if (data.resetText == null) $el.data('resetText', $el[val]())
|
||||
|
||||
$el[val](data[state] == null ? this.options[state] : data[state])
|
||||
|
||||
// push to event loop to allow forms to submit
|
||||
setTimeout($.proxy(function () {
|
||||
if (state == 'loadingText') {
|
||||
this.isLoading = true
|
||||
$el.addClass(d).attr(d, d)
|
||||
} else if (this.isLoading) {
|
||||
this.isLoading = false
|
||||
$el.removeClass(d).removeAttr(d)
|
||||
}
|
||||
}, this), 0)
|
||||
}
|
||||
|
||||
Button.prototype.toggle = function () {
|
||||
var changed = true
|
||||
var $parent = this.$element.closest('[data-toggle="buttons"]')
|
||||
|
||||
if ($parent.length) {
|
||||
var $input = this.$element.find('input')
|
||||
if ($input.prop('type') == 'radio') {
|
||||
if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
|
||||
else $parent.find('.active').removeClass('active')
|
||||
}
|
||||
if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
|
||||
}
|
||||
|
||||
if (changed) this.$element.toggleClass('active')
|
||||
}
|
||||
|
||||
|
||||
// BUTTON PLUGIN DEFINITION
|
||||
// ========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.button')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data) $this.data('bs.button', (data = new Button(this, options)))
|
||||
|
||||
if (option == 'toggle') data.toggle()
|
||||
else if (option) data.setState(option)
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.button
|
||||
|
||||
$.fn.button = Plugin
|
||||
$.fn.button.Constructor = Button
|
||||
|
||||
|
||||
// BUTTON NO CONFLICT
|
||||
// ==================
|
||||
|
||||
$.fn.button.noConflict = function () {
|
||||
$.fn.button = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// BUTTON DATA-API
|
||||
// ===============
|
||||
|
||||
$(document).on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
|
||||
var $btn = $(e.target)
|
||||
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
|
||||
Plugin.call($btn, 'toggle')
|
||||
e.preventDefault()
|
||||
})
|
||||
|
||||
}(jQuery);
|
@ -1,223 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: carousel.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#carousel
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// CAROUSEL CLASS DEFINITION
|
||||
// =========================
|
||||
|
||||
var Carousel = function (element, options) {
|
||||
this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
|
||||
this.$indicators = this.$element.find('.carousel-indicators')
|
||||
this.options = options
|
||||
this.paused =
|
||||
this.sliding =
|
||||
this.interval =
|
||||
this.$active =
|
||||
this.$items = null
|
||||
|
||||
this.options.pause == 'hover' && this.$element
|
||||
.on('mouseenter.bs.carousel', $.proxy(this.pause, this))
|
||||
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
|
||||
}
|
||||
|
||||
Carousel.VERSION = '3.2.0'
|
||||
|
||||
Carousel.DEFAULTS = {
|
||||
interval: 5000,
|
||||
pause: 'hover',
|
||||
wrap: true
|
||||
}
|
||||
|
||||
Carousel.prototype.keydown = function (e) {
|
||||
switch (e.which) {
|
||||
case 37: this.prev(); break
|
||||
case 39: this.next(); break
|
||||
default: return
|
||||
}
|
||||
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
Carousel.prototype.cycle = function (e) {
|
||||
e || (this.paused = false)
|
||||
|
||||
this.interval && clearInterval(this.interval)
|
||||
|
||||
this.options.interval
|
||||
&& !this.paused
|
||||
&& (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
Carousel.prototype.getItemIndex = function (item) {
|
||||
this.$items = item.parent().children('.item')
|
||||
return this.$items.index(item || this.$active)
|
||||
}
|
||||
|
||||
Carousel.prototype.to = function (pos) {
|
||||
var that = this
|
||||
var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
|
||||
|
||||
if (pos > (this.$items.length - 1) || pos < 0) return
|
||||
|
||||
if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
|
||||
if (activeIndex == pos) return this.pause().cycle()
|
||||
|
||||
return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
|
||||
}
|
||||
|
||||
Carousel.prototype.pause = function (e) {
|
||||
e || (this.paused = true)
|
||||
|
||||
if (this.$element.find('.next, .prev').length && $.support.transition) {
|
||||
this.$element.trigger($.support.transition.end)
|
||||
this.cycle(true)
|
||||
}
|
||||
|
||||
this.interval = clearInterval(this.interval)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
Carousel.prototype.next = function () {
|
||||
if (this.sliding) return
|
||||
return this.slide('next')
|
||||
}
|
||||
|
||||
Carousel.prototype.prev = function () {
|
||||
if (this.sliding) return
|
||||
return this.slide('prev')
|
||||
}
|
||||
|
||||
Carousel.prototype.slide = function (type, next) {
|
||||
var $active = this.$element.find('.item.active')
|
||||
var $next = next || $active[type]()
|
||||
var isCycling = this.interval
|
||||
var direction = type == 'next' ? 'left' : 'right'
|
||||
var fallback = type == 'next' ? 'first' : 'last'
|
||||
var that = this
|
||||
|
||||
if (!$next.length) {
|
||||
if (!this.options.wrap) return
|
||||
$next = this.$element.find('.item')[fallback]()
|
||||
}
|
||||
|
||||
if ($next.hasClass('active')) return (this.sliding = false)
|
||||
|
||||
var relatedTarget = $next[0]
|
||||
var slideEvent = $.Event('slide.bs.carousel', {
|
||||
relatedTarget: relatedTarget,
|
||||
direction: direction
|
||||
})
|
||||
this.$element.trigger(slideEvent)
|
||||
if (slideEvent.isDefaultPrevented()) return
|
||||
|
||||
this.sliding = true
|
||||
|
||||
isCycling && this.pause()
|
||||
|
||||
if (this.$indicators.length) {
|
||||
this.$indicators.find('.active').removeClass('active')
|
||||
var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
|
||||
$nextIndicator && $nextIndicator.addClass('active')
|
||||
}
|
||||
|
||||
var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
|
||||
if ($.support.transition && this.$element.hasClass('slide')) {
|
||||
$next.addClass(type)
|
||||
$next[0].offsetWidth // force reflow
|
||||
$active.addClass(direction)
|
||||
$next.addClass(direction)
|
||||
$active
|
||||
.one('bsTransitionEnd', function () {
|
||||
$next.removeClass([type, direction].join(' ')).addClass('active')
|
||||
$active.removeClass(['active', direction].join(' '))
|
||||
that.sliding = false
|
||||
setTimeout(function () {
|
||||
that.$element.trigger(slidEvent)
|
||||
}, 0)
|
||||
})
|
||||
.emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000)
|
||||
} else {
|
||||
$active.removeClass('active')
|
||||
$next.addClass('active')
|
||||
this.sliding = false
|
||||
this.$element.trigger(slidEvent)
|
||||
}
|
||||
|
||||
isCycling && this.cycle()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// CAROUSEL PLUGIN DEFINITION
|
||||
// ==========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.carousel')
|
||||
var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
var action = typeof option == 'string' ? option : options.slide
|
||||
|
||||
if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
|
||||
if (typeof option == 'number') data.to(option)
|
||||
else if (action) data[action]()
|
||||
else if (options.interval) data.pause().cycle()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.carousel
|
||||
|
||||
$.fn.carousel = Plugin
|
||||
$.fn.carousel.Constructor = Carousel
|
||||
|
||||
|
||||
// CAROUSEL NO CONFLICT
|
||||
// ====================
|
||||
|
||||
$.fn.carousel.noConflict = function () {
|
||||
$.fn.carousel = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// CAROUSEL DATA-API
|
||||
// =================
|
||||
|
||||
$(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
|
||||
var href
|
||||
var $this = $(this)
|
||||
var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
|
||||
if (!$target.hasClass('carousel')) return
|
||||
var options = $.extend({}, $target.data(), $this.data())
|
||||
var slideIndex = $this.attr('data-slide-to')
|
||||
if (slideIndex) options.interval = false
|
||||
|
||||
Plugin.call($target, options)
|
||||
|
||||
if (slideIndex) {
|
||||
$target.data('bs.carousel').to(slideIndex)
|
||||
}
|
||||
|
||||
e.preventDefault()
|
||||
})
|
||||
|
||||
$(window).on('load', function () {
|
||||
$('[data-ride="carousel"]').each(function () {
|
||||
var $carousel = $(this)
|
||||
Plugin.call($carousel, $carousel.data())
|
||||
})
|
||||
})
|
||||
|
||||
}(jQuery);
|
@ -1,170 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: collapse.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#collapse
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// COLLAPSE PUBLIC CLASS DEFINITION
|
||||
// ================================
|
||||
|
||||
var Collapse = function (element, options) {
|
||||
this.$element = $(element)
|
||||
this.options = $.extend({}, Collapse.DEFAULTS, options)
|
||||
this.transitioning = null
|
||||
|
||||
if (this.options.parent) this.$parent = $(this.options.parent)
|
||||
if (this.options.toggle) this.toggle()
|
||||
}
|
||||
|
||||
Collapse.VERSION = '3.2.0'
|
||||
|
||||
Collapse.DEFAULTS = {
|
||||
toggle: true
|
||||
}
|
||||
|
||||
Collapse.prototype.dimension = function () {
|
||||
var hasWidth = this.$element.hasClass('width')
|
||||
return hasWidth ? 'width' : 'height'
|
||||
}
|
||||
|
||||
Collapse.prototype.show = function () {
|
||||
if (this.transitioning || this.$element.hasClass('in')) return
|
||||
|
||||
var startEvent = $.Event('show.bs.collapse')
|
||||
this.$element.trigger(startEvent)
|
||||
if (startEvent.isDefaultPrevented()) return
|
||||
|
||||
var actives = this.$parent && this.$parent.find('> .panel > .in')
|
||||
|
||||
if (actives && actives.length) {
|
||||
var hasData = actives.data('bs.collapse')
|
||||
if (hasData && hasData.transitioning) return
|
||||
Plugin.call(actives, 'hide')
|
||||
hasData || actives.data('bs.collapse', null)
|
||||
}
|
||||
|
||||
var dimension = this.dimension()
|
||||
|
||||
this.$element
|
||||
.removeClass('collapse')
|
||||
.addClass('collapsing')[dimension](0)
|
||||
|
||||
this.transitioning = 1
|
||||
|
||||
var complete = function () {
|
||||
this.$element
|
||||
.removeClass('collapsing')
|
||||
.addClass('collapse in')[dimension]('')
|
||||
this.transitioning = 0
|
||||
this.$element
|
||||
.trigger('shown.bs.collapse')
|
||||
}
|
||||
|
||||
if (!$.support.transition) return complete.call(this)
|
||||
|
||||
var scrollSize = $.camelCase(['scroll', dimension].join('-'))
|
||||
|
||||
this.$element
|
||||
.one('bsTransitionEnd', $.proxy(complete, this))
|
||||
.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
|
||||
}
|
||||
|
||||
Collapse.prototype.hide = function () {
|
||||
if (this.transitioning || !this.$element.hasClass('in')) return
|
||||
|
||||
var startEvent = $.Event('hide.bs.collapse')
|
||||
this.$element.trigger(startEvent)
|
||||
if (startEvent.isDefaultPrevented()) return
|
||||
|
||||
var dimension = this.dimension()
|
||||
|
||||
this.$element[dimension](this.$element[dimension]())[0].offsetHeight
|
||||
|
||||
this.$element
|
||||
.addClass('collapsing')
|
||||
.removeClass('collapse')
|
||||
.removeClass('in')
|
||||
|
||||
this.transitioning = 1
|
||||
|
||||
var complete = function () {
|
||||
this.transitioning = 0
|
||||
this.$element
|
||||
.trigger('hidden.bs.collapse')
|
||||
.removeClass('collapsing')
|
||||
.addClass('collapse')
|
||||
}
|
||||
|
||||
if (!$.support.transition) return complete.call(this)
|
||||
|
||||
this.$element
|
||||
[dimension](0)
|
||||
.one('bsTransitionEnd', $.proxy(complete, this))
|
||||
.emulateTransitionEnd(350)
|
||||
}
|
||||
|
||||
Collapse.prototype.toggle = function () {
|
||||
this[this.$element.hasClass('in') ? 'hide' : 'show']()
|
||||
}
|
||||
|
||||
|
||||
// COLLAPSE PLUGIN DEFINITION
|
||||
// ==========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.collapse')
|
||||
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
|
||||
if (!data && options.toggle && option == 'show') option = !option
|
||||
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.collapse
|
||||
|
||||
$.fn.collapse = Plugin
|
||||
$.fn.collapse.Constructor = Collapse
|
||||
|
||||
|
||||
// COLLAPSE NO CONFLICT
|
||||
// ====================
|
||||
|
||||
$.fn.collapse.noConflict = function () {
|
||||
$.fn.collapse = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// COLLAPSE DATA-API
|
||||
// =================
|
||||
|
||||
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
|
||||
var href
|
||||
var $this = $(this)
|
||||
var target = $this.attr('data-target')
|
||||
|| e.preventDefault()
|
||||
|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
|
||||
var $target = $(target)
|
||||
var data = $target.data('bs.collapse')
|
||||
var option = data ? 'toggle' : $this.data()
|
||||
var parent = $this.attr('data-parent')
|
||||
var $parent = parent && $(parent)
|
||||
|
||||
if (!data || !data.transitioning) {
|
||||
if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
|
||||
$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
|
||||
}
|
||||
|
||||
Plugin.call($target, option)
|
||||
})
|
||||
|
||||
}(jQuery);
|
@ -1,151 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: dropdown.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#dropdowns
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// DROPDOWN CLASS DEFINITION
|
||||
// =========================
|
||||
|
||||
var backdrop = '.dropdown-backdrop'
|
||||
var toggle = '[data-toggle="dropdown"]'
|
||||
var Dropdown = function (element) {
|
||||
$(element).on('click.bs.dropdown', this.toggle)
|
||||
}
|
||||
|
||||
Dropdown.VERSION = '3.2.0'
|
||||
|
||||
Dropdown.prototype.toggle = function (e) {
|
||||
var $this = $(this)
|
||||
|
||||
if ($this.is('.disabled, :disabled')) return
|
||||
|
||||
var $parent = getParent($this)
|
||||
var isActive = $parent.hasClass('open')
|
||||
|
||||
clearMenus()
|
||||
|
||||
if (!isActive) {
|
||||
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
|
||||
// if mobile we use a backdrop because click events don't delegate
|
||||
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
|
||||
}
|
||||
|
||||
var relatedTarget = { relatedTarget: this }
|
||||
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
$this.trigger('focus')
|
||||
|
||||
$parent
|
||||
.toggleClass('open')
|
||||
.trigger('shown.bs.dropdown', relatedTarget)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Dropdown.prototype.keydown = function (e) {
|
||||
if (!/(38|40|27)/.test(e.keyCode)) return
|
||||
|
||||
var $this = $(this)
|
||||
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
if ($this.is('.disabled, :disabled')) return
|
||||
|
||||
var $parent = getParent($this)
|
||||
var isActive = $parent.hasClass('open')
|
||||
|
||||
if (!isActive || (isActive && e.keyCode == 27)) {
|
||||
if (e.which == 27) $parent.find(toggle).trigger('focus')
|
||||
return $this.trigger('click')
|
||||
}
|
||||
|
||||
var desc = ' li:not(.divider):visible a'
|
||||
var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
|
||||
|
||||
if (!$items.length) return
|
||||
|
||||
var index = $items.index($items.filter(':focus'))
|
||||
|
||||
if (e.keyCode == 38 && index > 0) index-- // up
|
||||
if (e.keyCode == 40 && index < $items.length - 1) index++ // down
|
||||
if (!~index) index = 0
|
||||
|
||||
$items.eq(index).trigger('focus')
|
||||
}
|
||||
|
||||
function clearMenus(e) {
|
||||
if (e && e.which === 3) return
|
||||
$(backdrop).remove()
|
||||
$(toggle).each(function () {
|
||||
var $parent = getParent($(this))
|
||||
var relatedTarget = { relatedTarget: this }
|
||||
if (!$parent.hasClass('open')) return
|
||||
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
|
||||
if (e.isDefaultPrevented()) return
|
||||
$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
|
||||
})
|
||||
}
|
||||
|
||||
function getParent($this) {
|
||||
var selector = $this.attr('data-target')
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
|
||||
}
|
||||
|
||||
var $parent = selector && $(selector)
|
||||
|
||||
return $parent && $parent.length ? $parent : $this.parent()
|
||||
}
|
||||
|
||||
|
||||
// DROPDOWN PLUGIN DEFINITION
|
||||
// ==========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.dropdown')
|
||||
|
||||
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
|
||||
if (typeof option == 'string') data[option].call($this)
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.dropdown
|
||||
|
||||
$.fn.dropdown = Plugin
|
||||
$.fn.dropdown.Constructor = Dropdown
|
||||
|
||||
|
||||
// DROPDOWN NO CONFLICT
|
||||
// ====================
|
||||
|
||||
$.fn.dropdown.noConflict = function () {
|
||||
$.fn.dropdown = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// APPLY TO STANDARD DROPDOWN ELEMENTS
|
||||
// ===================================
|
||||
|
||||
$(document)
|
||||
.on('click.bs.dropdown.data-api', clearMenus)
|
||||
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
|
||||
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
|
||||
.on('keydown.bs.dropdown.data-api', toggle + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown)
|
||||
|
||||
}(jQuery);
|
@ -1,280 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: modal.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#modals
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// MODAL CLASS DEFINITION
|
||||
// ======================
|
||||
|
||||
var Modal = function (element, options) {
|
||||
this.options = options
|
||||
this.$body = $(document.body)
|
||||
this.$element = $(element)
|
||||
this.$backdrop =
|
||||
this.isShown = null
|
||||
this.scrollbarWidth = 0
|
||||
|
||||
if (this.options.remote) {
|
||||
this.$element
|
||||
.find('.modal-content')
|
||||
.load(this.options.remote, $.proxy(function () {
|
||||
this.$element.trigger('loaded.bs.modal')
|
||||
}, this))
|
||||
}
|
||||
}
|
||||
|
||||
Modal.VERSION = '3.2.0'
|
||||
|
||||
Modal.DEFAULTS = {
|
||||
backdrop: true,
|
||||
keyboard: true,
|
||||
show: true
|
||||
}
|
||||
|
||||
Modal.prototype.toggle = function (_relatedTarget) {
|
||||
return this.isShown ? this.hide() : this.show(_relatedTarget)
|
||||
}
|
||||
|
||||
Modal.prototype.show = function (_relatedTarget) {
|
||||
var that = this
|
||||
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (this.isShown || e.isDefaultPrevented()) return
|
||||
|
||||
this.isShown = true
|
||||
|
||||
this.checkScrollbar()
|
||||
this.$body.addClass('modal-open')
|
||||
|
||||
this.setScrollbar()
|
||||
this.escape()
|
||||
|
||||
this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
|
||||
|
||||
this.backdrop(function () {
|
||||
var transition = $.support.transition && that.$element.hasClass('fade')
|
||||
|
||||
if (!that.$element.parent().length) {
|
||||
that.$element.appendTo(that.$body) // don't move modals dom position
|
||||
}
|
||||
|
||||
that.$element
|
||||
.show()
|
||||
.scrollTop(0)
|
||||
|
||||
if (transition) {
|
||||
that.$element[0].offsetWidth // force reflow
|
||||
}
|
||||
|
||||
that.$element
|
||||
.addClass('in')
|
||||
.attr('aria-hidden', false)
|
||||
|
||||
that.enforceFocus()
|
||||
|
||||
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
|
||||
|
||||
transition ?
|
||||
that.$element.find('.modal-dialog') // wait for modal to slide in
|
||||
.one('bsTransitionEnd', function () {
|
||||
that.$element.trigger('focus').trigger(e)
|
||||
})
|
||||
.emulateTransitionEnd(300) :
|
||||
that.$element.trigger('focus').trigger(e)
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.hide = function (e) {
|
||||
if (e) e.preventDefault()
|
||||
|
||||
e = $.Event('hide.bs.modal')
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (!this.isShown || e.isDefaultPrevented()) return
|
||||
|
||||
this.isShown = false
|
||||
|
||||
this.$body.removeClass('modal-open')
|
||||
|
||||
this.resetScrollbar()
|
||||
this.escape()
|
||||
|
||||
$(document).off('focusin.bs.modal')
|
||||
|
||||
this.$element
|
||||
.removeClass('in')
|
||||
.attr('aria-hidden', true)
|
||||
.off('click.dismiss.bs.modal')
|
||||
|
||||
$.support.transition && this.$element.hasClass('fade') ?
|
||||
this.$element
|
||||
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
|
||||
.emulateTransitionEnd(300) :
|
||||
this.hideModal()
|
||||
}
|
||||
|
||||
Modal.prototype.enforceFocus = function () {
|
||||
$(document)
|
||||
.off('focusin.bs.modal') // guard against infinite focus loop
|
||||
.on('focusin.bs.modal', $.proxy(function (e) {
|
||||
if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
|
||||
this.$element.trigger('focus')
|
||||
}
|
||||
}, this))
|
||||
}
|
||||
|
||||
Modal.prototype.escape = function () {
|
||||
if (this.isShown && this.options.keyboard) {
|
||||
this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
|
||||
e.which == 27 && this.hide()
|
||||
}, this))
|
||||
} else if (!this.isShown) {
|
||||
this.$element.off('keyup.dismiss.bs.modal')
|
||||
}
|
||||
}
|
||||
|
||||
Modal.prototype.hideModal = function () {
|
||||
var that = this
|
||||
this.$element.hide()
|
||||
this.backdrop(function () {
|
||||
that.$element.trigger('hidden.bs.modal')
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.removeBackdrop = function () {
|
||||
this.$backdrop && this.$backdrop.remove()
|
||||
this.$backdrop = null
|
||||
}
|
||||
|
||||
Modal.prototype.backdrop = function (callback) {
|
||||
var that = this
|
||||
var animate = this.$element.hasClass('fade') ? 'fade' : ''
|
||||
|
||||
if (this.isShown && this.options.backdrop) {
|
||||
var doAnimate = $.support.transition && animate
|
||||
|
||||
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
|
||||
.appendTo(this.$body)
|
||||
|
||||
this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
|
||||
if (e.target !== e.currentTarget) return
|
||||
this.options.backdrop == 'static'
|
||||
? this.$element[0].focus.call(this.$element[0])
|
||||
: this.hide.call(this)
|
||||
}, this))
|
||||
|
||||
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
|
||||
|
||||
this.$backdrop.addClass('in')
|
||||
|
||||
if (!callback) return
|
||||
|
||||
doAnimate ?
|
||||
this.$backdrop
|
||||
.one('bsTransitionEnd', callback)
|
||||
.emulateTransitionEnd(150) :
|
||||
callback()
|
||||
|
||||
} else if (!this.isShown && this.$backdrop) {
|
||||
this.$backdrop.removeClass('in')
|
||||
|
||||
var callbackRemove = function () {
|
||||
that.removeBackdrop()
|
||||
callback && callback()
|
||||
}
|
||||
$.support.transition && this.$element.hasClass('fade') ?
|
||||
this.$backdrop
|
||||
.one('bsTransitionEnd', callbackRemove)
|
||||
.emulateTransitionEnd(150) :
|
||||
callbackRemove()
|
||||
|
||||
} else if (callback) {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
Modal.prototype.checkScrollbar = function () {
|
||||
if (document.body.clientWidth >= window.innerWidth) return
|
||||
this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar()
|
||||
}
|
||||
|
||||
Modal.prototype.setScrollbar = function () {
|
||||
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
|
||||
if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
|
||||
}
|
||||
|
||||
Modal.prototype.resetScrollbar = function () {
|
||||
this.$body.css('padding-right', '')
|
||||
}
|
||||
|
||||
Modal.prototype.measureScrollbar = function () { // thx walsh
|
||||
var scrollDiv = document.createElement('div')
|
||||
scrollDiv.className = 'modal-scrollbar-measure'
|
||||
this.$body.append(scrollDiv)
|
||||
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
|
||||
this.$body[0].removeChild(scrollDiv)
|
||||
return scrollbarWidth
|
||||
}
|
||||
|
||||
|
||||
// MODAL PLUGIN DEFINITION
|
||||
// =======================
|
||||
|
||||
function Plugin(option, _relatedTarget) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.modal')
|
||||
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
|
||||
if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
|
||||
if (typeof option == 'string') data[option](_relatedTarget)
|
||||
else if (options.show) data.show(_relatedTarget)
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.modal
|
||||
|
||||
$.fn.modal = Plugin
|
||||
$.fn.modal.Constructor = Modal
|
||||
|
||||
|
||||
// MODAL NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.modal.noConflict = function () {
|
||||
$.fn.modal = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// MODAL DATA-API
|
||||
// ==============
|
||||
|
||||
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
|
||||
var $this = $(this)
|
||||
var href = $this.attr('href')
|
||||
var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
|
||||
var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
|
||||
|
||||
if ($this.is('a')) e.preventDefault()
|
||||
|
||||
$target.one('show.bs.modal', function (showEvent) {
|
||||
if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
|
||||
$target.one('hidden.bs.modal', function () {
|
||||
$this.is(':visible') && $this.trigger('focus')
|
||||
})
|
||||
})
|
||||
Plugin.call($target, option, this)
|
||||
})
|
||||
|
||||
}(jQuery);
|
@ -1,113 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: popover.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#popovers
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// POPOVER PUBLIC CLASS DEFINITION
|
||||
// ===============================
|
||||
|
||||
var Popover = function (element, options) {
|
||||
this.init('popover', element, options)
|
||||
}
|
||||
|
||||
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
|
||||
|
||||
Popover.VERSION = '3.2.0'
|
||||
|
||||
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
|
||||
placement: 'right',
|
||||
trigger: 'click',
|
||||
content: '',
|
||||
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
|
||||
})
|
||||
|
||||
|
||||
// NOTE: POPOVER EXTENDS tooltip.js
|
||||
// ================================
|
||||
|
||||
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
|
||||
|
||||
Popover.prototype.constructor = Popover
|
||||
|
||||
Popover.prototype.getDefaults = function () {
|
||||
return Popover.DEFAULTS
|
||||
}
|
||||
|
||||
Popover.prototype.setContent = function () {
|
||||
var $tip = this.tip()
|
||||
var title = this.getTitle()
|
||||
var content = this.getContent()
|
||||
|
||||
$tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
|
||||
$tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events
|
||||
this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
|
||||
](content)
|
||||
|
||||
$tip.removeClass('fade top bottom left right in')
|
||||
|
||||
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
|
||||
// this manually by checking the contents.
|
||||
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
|
||||
}
|
||||
|
||||
Popover.prototype.hasContent = function () {
|
||||
return this.getTitle() || this.getContent()
|
||||
}
|
||||
|
||||
Popover.prototype.getContent = function () {
|
||||
var $e = this.$element
|
||||
var o = this.options
|
||||
|
||||
return $e.attr('data-content')
|
||||
|| (typeof o.content == 'function' ?
|
||||
o.content.call($e[0]) :
|
||||
o.content)
|
||||
}
|
||||
|
||||
Popover.prototype.arrow = function () {
|
||||
return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
|
||||
}
|
||||
|
||||
Popover.prototype.tip = function () {
|
||||
if (!this.$tip) this.$tip = $(this.options.template)
|
||||
return this.$tip
|
||||
}
|
||||
|
||||
|
||||
// POPOVER PLUGIN DEFINITION
|
||||
// =========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.popover')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data && option == 'destroy') return
|
||||
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.popover
|
||||
|
||||
$.fn.popover = Plugin
|
||||
$.fn.popover.Constructor = Popover
|
||||
|
||||
|
||||
// POPOVER NO CONFLICT
|
||||
// ===================
|
||||
|
||||
$.fn.popover.noConflict = function () {
|
||||
$.fn.popover = old
|
||||
return this
|
||||
}
|
||||
|
||||
}(jQuery);
|
@ -1,170 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: scrollspy.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#scrollspy
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// SCROLLSPY CLASS DEFINITION
|
||||
// ==========================
|
||||
|
||||
function ScrollSpy(element, options) {
|
||||
var process = $.proxy(this.process, this)
|
||||
|
||||
this.$body = $('body')
|
||||
this.$scrollElement = $(element).is('body') ? $(window) : $(element)
|
||||
this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
|
||||
this.selector = (this.options.target || '') + ' .nav li > a'
|
||||
this.offsets = []
|
||||
this.targets = []
|
||||
this.activeTarget = null
|
||||
this.scrollHeight = 0
|
||||
|
||||
this.$scrollElement.on('scroll.bs.scrollspy', process)
|
||||
this.refresh()
|
||||
this.process()
|
||||
}
|
||||
|
||||
ScrollSpy.VERSION = '3.2.0'
|
||||
|
||||
ScrollSpy.DEFAULTS = {
|
||||
offset: 10
|
||||
}
|
||||
|
||||
ScrollSpy.prototype.getScrollHeight = function () {
|
||||
return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
|
||||
}
|
||||
|
||||
ScrollSpy.prototype.refresh = function () {
|
||||
var offsetMethod = 'offset'
|
||||
var offsetBase = 0
|
||||
|
||||
if (!$.isWindow(this.$scrollElement[0])) {
|
||||
offsetMethod = 'position'
|
||||
offsetBase = this.$scrollElement.scrollTop()
|
||||
}
|
||||
|
||||
this.offsets = []
|
||||
this.targets = []
|
||||
this.scrollHeight = this.getScrollHeight()
|
||||
|
||||
var self = this
|
||||
|
||||
this.$body
|
||||
.find(this.selector)
|
||||
.map(function () {
|
||||
var $el = $(this)
|
||||
var href = $el.data('target') || $el.attr('href')
|
||||
var $href = /^#./.test(href) && $(href)
|
||||
|
||||
return ($href
|
||||
&& $href.length
|
||||
&& $href.is(':visible')
|
||||
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null
|
||||
})
|
||||
.sort(function (a, b) { return a[0] - b[0] })
|
||||
.each(function () {
|
||||
self.offsets.push(this[0])
|
||||
self.targets.push(this[1])
|
||||
})
|
||||
}
|
||||
|
||||
ScrollSpy.prototype.process = function () {
|
||||
var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
|
||||
var scrollHeight = this.getScrollHeight()
|
||||
var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
|
||||
var offsets = this.offsets
|
||||
var targets = this.targets
|
||||
var activeTarget = this.activeTarget
|
||||
var i
|
||||
|
||||
if (this.scrollHeight != scrollHeight) {
|
||||
this.refresh()
|
||||
}
|
||||
|
||||
if (scrollTop >= maxScroll) {
|
||||
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
|
||||
}
|
||||
|
||||
if (activeTarget && scrollTop <= offsets[0]) {
|
||||
return activeTarget != (i = targets[0]) && this.activate(i)
|
||||
}
|
||||
|
||||
for (i = offsets.length; i--;) {
|
||||
activeTarget != targets[i]
|
||||
&& scrollTop >= offsets[i]
|
||||
&& (!offsets[i + 1] || scrollTop <= offsets[i + 1])
|
||||
&& this.activate(targets[i])
|
||||
}
|
||||
}
|
||||
|
||||
ScrollSpy.prototype.activate = function (target) {
|
||||
this.activeTarget = target
|
||||
|
||||
$(this.selector)
|
||||
.parentsUntil(this.options.target, '.active')
|
||||
.removeClass('active')
|
||||
|
||||
var selector = this.selector +
|
||||
'[data-target="' + target + '"],' +
|
||||
this.selector + '[href="' + target + '"]'
|
||||
|
||||
var active = $(selector)
|
||||
.parents('li')
|
||||
.addClass('active')
|
||||
|
||||
if (active.parent('.dropdown-menu').length) {
|
||||
active = active
|
||||
.closest('li.dropdown')
|
||||
.addClass('active')
|
||||
}
|
||||
|
||||
active.trigger('activate.bs.scrollspy')
|
||||
}
|
||||
|
||||
|
||||
// SCROLLSPY PLUGIN DEFINITION
|
||||
// ===========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.scrollspy')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.scrollspy
|
||||
|
||||
$.fn.scrollspy = Plugin
|
||||
$.fn.scrollspy.Constructor = ScrollSpy
|
||||
|
||||
|
||||
// SCROLLSPY NO CONFLICT
|
||||
// =====================
|
||||
|
||||
$.fn.scrollspy.noConflict = function () {
|
||||
$.fn.scrollspy = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// SCROLLSPY DATA-API
|
||||
// ==================
|
||||
|
||||
$(window).on('load.bs.scrollspy.data-api', function () {
|
||||
$('[data-spy="scroll"]').each(function () {
|
||||
var $spy = $(this)
|
||||
Plugin.call($spy, $spy.data())
|
||||
})
|
||||
})
|
||||
|
||||
}(jQuery);
|
@ -1,128 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: tab.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#tabs
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// TAB CLASS DEFINITION
|
||||
// ====================
|
||||
|
||||
var Tab = function (element) {
|
||||
this.element = $(element)
|
||||
}
|
||||
|
||||
Tab.VERSION = '3.2.0'
|
||||
|
||||
Tab.prototype.show = function () {
|
||||
var $this = this.element
|
||||
var $ul = $this.closest('ul:not(.dropdown-menu)')
|
||||
var selector = $this.data('target')
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
|
||||
}
|
||||
|
||||
if ($this.parent('li').hasClass('active')) return
|
||||
|
||||
var previous = $ul.find('.active:last a')[0]
|
||||
var e = $.Event('show.bs.tab', {
|
||||
relatedTarget: previous
|
||||
})
|
||||
|
||||
$this.trigger(e)
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
var $target = $(selector)
|
||||
|
||||
this.activate($this.closest('li'), $ul)
|
||||
this.activate($target, $target.parent(), function () {
|
||||
$this.trigger({
|
||||
type: 'shown.bs.tab',
|
||||
relatedTarget: previous
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Tab.prototype.activate = function (element, container, callback) {
|
||||
var $active = container.find('> .active')
|
||||
var transition = callback
|
||||
&& $.support.transition
|
||||
&& $active.hasClass('fade')
|
||||
|
||||
function next() {
|
||||
$active
|
||||
.removeClass('active')
|
||||
.find('> .dropdown-menu > .active')
|
||||
.removeClass('active')
|
||||
|
||||
element.addClass('active')
|
||||
|
||||
if (transition) {
|
||||
element[0].offsetWidth // reflow for transition
|
||||
element.addClass('in')
|
||||
} else {
|
||||
element.removeClass('fade')
|
||||
}
|
||||
|
||||
if (element.parent('.dropdown-menu')) {
|
||||
element.closest('li.dropdown').addClass('active')
|
||||
}
|
||||
|
||||
callback && callback()
|
||||
}
|
||||
|
||||
transition ?
|
||||
$active
|
||||
.one('bsTransitionEnd', next)
|
||||
.emulateTransitionEnd(150) :
|
||||
next()
|
||||
|
||||
$active.removeClass('in')
|
||||
}
|
||||
|
||||
|
||||
// TAB PLUGIN DEFINITION
|
||||
// =====================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.tab')
|
||||
|
||||
if (!data) $this.data('bs.tab', (data = new Tab(this)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.tab
|
||||
|
||||
$.fn.tab = Plugin
|
||||
$.fn.tab.Constructor = Tab
|
||||
|
||||
|
||||
// TAB NO CONFLICT
|
||||
// ===============
|
||||
|
||||
$.fn.tab.noConflict = function () {
|
||||
$.fn.tab = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// TAB DATA-API
|
||||
// ============
|
||||
|
||||
$(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
|
||||
e.preventDefault()
|
||||
Plugin.call($(this), 'show')
|
||||
})
|
||||
|
||||
}(jQuery);
|
@ -1,457 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: tooltip.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#tooltip
|
||||
* Inspired by the original jQuery.tipsy by Jason Frame
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// TOOLTIP PUBLIC CLASS DEFINITION
|
||||
// ===============================
|
||||
|
||||
var Tooltip = function (element, options) {
|
||||
this.type =
|
||||
this.options =
|
||||
this.enabled =
|
||||
this.timeout =
|
||||
this.hoverState =
|
||||
this.$element = null
|
||||
|
||||
this.init('tooltip', element, options)
|
||||
}
|
||||
|
||||
Tooltip.VERSION = '3.2.0'
|
||||
|
||||
Tooltip.DEFAULTS = {
|
||||
animation: true,
|
||||
placement: 'top',
|
||||
selector: false,
|
||||
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
|
||||
trigger: 'hover focus',
|
||||
title: '',
|
||||
delay: 0,
|
||||
html: false,
|
||||
container: false,
|
||||
viewport: {
|
||||
selector: 'body',
|
||||
padding: 0
|
||||
}
|
||||
}
|
||||
|
||||
Tooltip.prototype.init = function (type, element, options) {
|
||||
this.enabled = true
|
||||
this.type = type
|
||||
this.$element = $(element)
|
||||
this.options = this.getOptions(options)
|
||||
this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
|
||||
|
||||
var triggers = this.options.trigger.split(' ')
|
||||
|
||||
for (var i = triggers.length; i--;) {
|
||||
var trigger = triggers[i]
|
||||
|
||||
if (trigger == 'click') {
|
||||
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
|
||||
} else if (trigger != 'manual') {
|
||||
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
|
||||
var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
|
||||
|
||||
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
|
||||
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
|
||||
}
|
||||
}
|
||||
|
||||
this.options.selector ?
|
||||
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
|
||||
this.fixTitle()
|
||||
}
|
||||
|
||||
Tooltip.prototype.getDefaults = function () {
|
||||
return Tooltip.DEFAULTS
|
||||
}
|
||||
|
||||
Tooltip.prototype.getOptions = function (options) {
|
||||
options = $.extend({}, this.getDefaults(), this.$element.data(), options)
|
||||
|
||||
if (options.delay && typeof options.delay == 'number') {
|
||||
options.delay = {
|
||||
show: options.delay,
|
||||
hide: options.delay
|
||||
}
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
Tooltip.prototype.getDelegateOptions = function () {
|
||||
var options = {}
|
||||
var defaults = this.getDefaults()
|
||||
|
||||
this._options && $.each(this._options, function (key, value) {
|
||||
if (defaults[key] != value) options[key] = value
|
||||
})
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
Tooltip.prototype.enter = function (obj) {
|
||||
var self = obj instanceof this.constructor ?
|
||||
obj : $(obj.currentTarget).data('bs.' + this.type)
|
||||
|
||||
if (!self) {
|
||||
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
|
||||
$(obj.currentTarget).data('bs.' + this.type, self)
|
||||
}
|
||||
|
||||
clearTimeout(self.timeout)
|
||||
|
||||
self.hoverState = 'in'
|
||||
|
||||
if (!self.options.delay || !self.options.delay.show) return self.show()
|
||||
|
||||
self.timeout = setTimeout(function () {
|
||||
if (self.hoverState == 'in') self.show()
|
||||
}, self.options.delay.show)
|
||||
}
|
||||
|
||||
Tooltip.prototype.leave = function (obj) {
|
||||
var self = obj instanceof this.constructor ?
|
||||
obj : $(obj.currentTarget).data('bs.' + this.type)
|
||||
|
||||
if (!self) {
|
||||
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
|
||||
$(obj.currentTarget).data('bs.' + this.type, self)
|
||||
}
|
||||
|
||||
clearTimeout(self.timeout)
|
||||
|
||||
self.hoverState = 'out'
|
||||
|
||||
if (!self.options.delay || !self.options.delay.hide) return self.hide()
|
||||
|
||||
self.timeout = setTimeout(function () {
|
||||
if (self.hoverState == 'out') self.hide()
|
||||
}, self.options.delay.hide)
|
||||
}
|
||||
|
||||
Tooltip.prototype.show = function () {
|
||||
var e = $.Event('show.bs.' + this.type)
|
||||
|
||||
if (this.hasContent() && this.enabled) {
|
||||
this.$element.trigger(e)
|
||||
|
||||
var inDom = $.contains(document.documentElement, this.$element[0])
|
||||
if (e.isDefaultPrevented() || !inDom) return
|
||||
var that = this
|
||||
|
||||
var $tip = this.tip()
|
||||
|
||||
var tipId = this.getUID(this.type)
|
||||
|
||||
this.setContent()
|
||||
$tip.attr('id', tipId)
|
||||
this.$element.attr('aria-describedby', tipId)
|
||||
|
||||
if (this.options.animation) $tip.addClass('fade')
|
||||
|
||||
var placement = typeof this.options.placement == 'function' ?
|
||||
this.options.placement.call(this, $tip[0], this.$element[0]) :
|
||||
this.options.placement
|
||||
|
||||
var autoToken = /\s?auto?\s?/i
|
||||
var autoPlace = autoToken.test(placement)
|
||||
if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
|
||||
|
||||
$tip
|
||||
.detach()
|
||||
.css({ top: 0, left: 0, display: 'block' })
|
||||
.addClass(placement)
|
||||
.data('bs.' + this.type, this)
|
||||
|
||||
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
|
||||
|
||||
var pos = this.getPosition()
|
||||
var actualWidth = $tip[0].offsetWidth
|
||||
var actualHeight = $tip[0].offsetHeight
|
||||
|
||||
if (autoPlace) {
|
||||
var orgPlacement = placement
|
||||
var $parent = this.$element.parent()
|
||||
var parentDim = this.getPosition($parent)
|
||||
|
||||
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
|
||||
placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
|
||||
placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
|
||||
placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
|
||||
placement
|
||||
|
||||
$tip
|
||||
.removeClass(orgPlacement)
|
||||
.addClass(placement)
|
||||
}
|
||||
|
||||
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
|
||||
|
||||
this.applyPlacement(calculatedOffset, placement)
|
||||
|
||||
var complete = function () {
|
||||
that.$element.trigger('shown.bs.' + that.type)
|
||||
that.hoverState = null
|
||||
}
|
||||
|
||||
$.support.transition && this.$tip.hasClass('fade') ?
|
||||
$tip
|
||||
.one('bsTransitionEnd', complete)
|
||||
.emulateTransitionEnd(150) :
|
||||
complete()
|
||||
}
|
||||
}
|
||||
|
||||
Tooltip.prototype.applyPlacement = function (offset, placement) {
|
||||
var $tip = this.tip()
|
||||
var width = $tip[0].offsetWidth
|
||||
var height = $tip[0].offsetHeight
|
||||
|
||||
// manually read margins because getBoundingClientRect includes difference
|
||||
var marginTop = parseInt($tip.css('margin-top'), 10)
|
||||
var marginLeft = parseInt($tip.css('margin-left'), 10)
|
||||
|
||||
// we must check for NaN for ie 8/9
|
||||
if (isNaN(marginTop)) marginTop = 0
|
||||
if (isNaN(marginLeft)) marginLeft = 0
|
||||
|
||||
offset.top = offset.top + marginTop
|
||||
offset.left = offset.left + marginLeft
|
||||
|
||||
// $.fn.offset doesn't round pixel values
|
||||
// so we use setOffset directly with our own function B-0
|
||||
$.offset.setOffset($tip[0], $.extend({
|
||||
using: function (props) {
|
||||
$tip.css({
|
||||
top: Math.round(props.top),
|
||||
left: Math.round(props.left)
|
||||
})
|
||||
}
|
||||
}, offset), 0)
|
||||
|
||||
$tip.addClass('in')
|
||||
|
||||
// check to see if placing tip in new offset caused the tip to resize itself
|
||||
var actualWidth = $tip[0].offsetWidth
|
||||
var actualHeight = $tip[0].offsetHeight
|
||||
|
||||
if (placement == 'top' && actualHeight != height) {
|
||||
offset.top = offset.top + height - actualHeight
|
||||
}
|
||||
|
||||
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
|
||||
|
||||
if (delta.left) offset.left += delta.left
|
||||
else offset.top += delta.top
|
||||
|
||||
var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
|
||||
var arrowPosition = delta.left ? 'left' : 'top'
|
||||
var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
|
||||
|
||||
$tip.offset(offset)
|
||||
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
|
||||
}
|
||||
|
||||
Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
|
||||
this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
|
||||
}
|
||||
|
||||
Tooltip.prototype.setContent = function () {
|
||||
var $tip = this.tip()
|
||||
var title = this.getTitle()
|
||||
|
||||
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
|
||||
$tip.removeClass('fade in top bottom left right')
|
||||
}
|
||||
|
||||
Tooltip.prototype.hide = function () {
|
||||
var that = this
|
||||
var $tip = this.tip()
|
||||
var e = $.Event('hide.bs.' + this.type)
|
||||
|
||||
this.$element.removeAttr('aria-describedby')
|
||||
|
||||
function complete() {
|
||||
if (that.hoverState != 'in') $tip.detach()
|
||||
that.$element.trigger('hidden.bs.' + that.type)
|
||||
}
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
$tip.removeClass('in')
|
||||
|
||||
$.support.transition && this.$tip.hasClass('fade') ?
|
||||
$tip
|
||||
.one('bsTransitionEnd', complete)
|
||||
.emulateTransitionEnd(150) :
|
||||
complete()
|
||||
|
||||
this.hoverState = null
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
Tooltip.prototype.fixTitle = function () {
|
||||
var $e = this.$element
|
||||
if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
|
||||
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
|
||||
}
|
||||
}
|
||||
|
||||
Tooltip.prototype.hasContent = function () {
|
||||
return this.getTitle()
|
||||
}
|
||||
|
||||
Tooltip.prototype.getPosition = function ($element) {
|
||||
$element = $element || this.$element
|
||||
var el = $element[0]
|
||||
var isBody = el.tagName == 'BODY'
|
||||
return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
|
||||
scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
|
||||
width: isBody ? $(window).width() : $element.outerWidth(),
|
||||
height: isBody ? $(window).height() : $element.outerHeight()
|
||||
}, isBody ? { top: 0, left: 0 } : $element.offset())
|
||||
}
|
||||
|
||||
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
|
||||
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
||||
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
||||
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
|
||||
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
|
||||
|
||||
}
|
||||
|
||||
Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
|
||||
var delta = { top: 0, left: 0 }
|
||||
if (!this.$viewport) return delta
|
||||
|
||||
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
|
||||
var viewportDimensions = this.getPosition(this.$viewport)
|
||||
|
||||
if (/right|left/.test(placement)) {
|
||||
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
|
||||
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
|
||||
if (topEdgeOffset < viewportDimensions.top) { // top overflow
|
||||
delta.top = viewportDimensions.top - topEdgeOffset
|
||||
} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
|
||||
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
|
||||
}
|
||||
} else {
|
||||
var leftEdgeOffset = pos.left - viewportPadding
|
||||
var rightEdgeOffset = pos.left + viewportPadding + actualWidth
|
||||
if (leftEdgeOffset < viewportDimensions.left) { // left overflow
|
||||
delta.left = viewportDimensions.left - leftEdgeOffset
|
||||
} else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
|
||||
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
|
||||
}
|
||||
}
|
||||
|
||||
return delta
|
||||
}
|
||||
|
||||
Tooltip.prototype.getTitle = function () {
|
||||
var title
|
||||
var $e = this.$element
|
||||
var o = this.options
|
||||
|
||||
title = $e.attr('data-original-title')
|
||||
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
|
||||
|
||||
return title
|
||||
}
|
||||
|
||||
Tooltip.prototype.getUID = function (prefix) {
|
||||
do prefix += ~~(Math.random() * 1000000)
|
||||
while (document.getElementById(prefix))
|
||||
return prefix
|
||||
}
|
||||
|
||||
Tooltip.prototype.tip = function () {
|
||||
return (this.$tip = this.$tip || $(this.options.template))
|
||||
}
|
||||
|
||||
Tooltip.prototype.arrow = function () {
|
||||
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
|
||||
}
|
||||
|
||||
Tooltip.prototype.validate = function () {
|
||||
if (!this.$element[0].parentNode) {
|
||||
this.hide()
|
||||
this.$element = null
|
||||
this.options = null
|
||||
}
|
||||
}
|
||||
|
||||
Tooltip.prototype.enable = function () {
|
||||
this.enabled = true
|
||||
}
|
||||
|
||||
Tooltip.prototype.disable = function () {
|
||||
this.enabled = false
|
||||
}
|
||||
|
||||
Tooltip.prototype.toggleEnabled = function () {
|
||||
this.enabled = !this.enabled
|
||||
}
|
||||
|
||||
Tooltip.prototype.toggle = function (e) {
|
||||
var self = this
|
||||
if (e) {
|
||||
self = $(e.currentTarget).data('bs.' + this.type)
|
||||
if (!self) {
|
||||
self = new this.constructor(e.currentTarget, this.getDelegateOptions())
|
||||
$(e.currentTarget).data('bs.' + this.type, self)
|
||||
}
|
||||
}
|
||||
|
||||
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
|
||||
}
|
||||
|
||||
Tooltip.prototype.destroy = function () {
|
||||
clearTimeout(this.timeout)
|
||||
this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
|
||||
}
|
||||
|
||||
|
||||
// TOOLTIP PLUGIN DEFINITION
|
||||
// =========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.tooltip')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data && option == 'destroy') return
|
||||
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.tooltip
|
||||
|
||||
$.fn.tooltip = Plugin
|
||||
$.fn.tooltip.Constructor = Tooltip
|
||||
|
||||
|
||||
// TOOLTIP NO CONFLICT
|
||||
// ===================
|
||||
|
||||
$.fn.tooltip.noConflict = function () {
|
||||
$.fn.tooltip = old
|
||||
return this
|
||||
}
|
||||
|
||||
}(jQuery);
|
@ -1,59 +0,0 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: transition.js v3.2.0
|
||||
* http://getbootstrap.com/javascript/#transitions
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
|
||||
// ============================================================
|
||||
|
||||
function transitionEnd() {
|
||||
var el = document.createElement('bootstrap')
|
||||
|
||||
var transEndEventNames = {
|
||||
WebkitTransition : 'webkitTransitionEnd',
|
||||
MozTransition : 'transitionend',
|
||||
OTransition : 'oTransitionEnd otransitionend',
|
||||
transition : 'transitionend'
|
||||
}
|
||||
|
||||
for (var name in transEndEventNames) {
|
||||
if (el.style[name] !== undefined) {
|
||||
return { end: transEndEventNames[name] }
|
||||
}
|
||||
}
|
||||
|
||||
return false // explicit for ie8 ( ._.)
|
||||
}
|
||||
|
||||
// http://blog.alexmaccaw.com/css-transitions
|
||||
$.fn.emulateTransitionEnd = function (duration) {
|
||||
var called = false
|
||||
var $el = this
|
||||
$(this).one('bsTransitionEnd', function () { called = true })
|
||||
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
|
||||
setTimeout(callback, duration)
|
||||
return this
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$.support.transition = transitionEnd()
|
||||
|
||||
if (!$.support.transition) return
|
||||
|
||||
$.event.special.bsTransitionEnd = {
|
||||
bindType: $.support.transition.end,
|
||||
delegateType: $.support.transition.end,
|
||||
handle: function (e) {
|
||||
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}(jQuery);
|
@ -1,819 +0,0 @@
|
||||
// Override Bootstrap variables here (defaults from bootstrap-sass v3.2.0.2):
|
||||
|
||||
// When true, asset path helpers are used, otherwise the regular CSS `url()` is used.
|
||||
// When there no function is defined, `fn('')` is parsed as string that equals the right hand side
|
||||
// NB: in Sass 3.3 there is a native function: function-exists(twbs-font-path)
|
||||
// $bootstrap-sass-asset-helper: (twbs-font-path("") != unquote('twbs-font-path("")'))
|
||||
|
||||
//
|
||||
// Variables
|
||||
// --------------------------------------------------
|
||||
|
||||
//== Colors
|
||||
//
|
||||
//## Gray and brand colors for use across Bootstrap.
|
||||
|
||||
// $gray-darker: lighten(#000, 13.5%) // #222
|
||||
// $gray-dark: lighten(#000, 20%) // #333
|
||||
// $gray: lighten(#000, 33.5%) // #555
|
||||
// $gray-light: lighten(#000, 46.7%) // #777
|
||||
// $gray-lighter: lighten(#000, 93.5%) // #eee
|
||||
|
||||
// $brand-primary: #428bca
|
||||
// $brand-success: #5cb85c
|
||||
// $brand-info: #5bc0de
|
||||
// $brand-warning: #f0ad4e
|
||||
// $brand-danger: #d9534f
|
||||
|
||||
//== Scaffolding
|
||||
//
|
||||
//## Settings for some of the most global styles.
|
||||
|
||||
//* Background color for `<body>`.
|
||||
// $body-bg: #fff
|
||||
//* Global text color on `<body>`.
|
||||
// $text-color: $gray-dark
|
||||
|
||||
//* Global textual link color.
|
||||
// $link-color: $brand-primary
|
||||
//* Link hover color set via `darken()` function.
|
||||
// $link-hover-color: darken($link-color, 15%)
|
||||
|
||||
//== Typography
|
||||
//
|
||||
//## Font, line-height, and color for body text, headings, and more.
|
||||
|
||||
// $font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif
|
||||
// $font-family-serif: Georgia, "Times New Roman", Times, serif
|
||||
//* Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
|
||||
// $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace
|
||||
// $font-family-base: $font-family-sans-serif
|
||||
|
||||
// $font-size-base: 14px
|
||||
// $font-size-large: ceil(($font-size-base * 1.25)) // ~18px
|
||||
// $font-size-small: ceil(($font-size-base * 0.85)) // ~12px
|
||||
|
||||
// $font-size-h1: floor(($font-size-base * 2.6)) // ~36px
|
||||
// $font-size-h2: floor(($font-size-base * 2.15)) // ~30px
|
||||
// $font-size-h3: ceil(($font-size-base * 1.7)) // ~24px
|
||||
// $font-size-h4: ceil(($font-size-base * 1.25)) // ~18px
|
||||
// $font-size-h5: $font-size-base
|
||||
// $font-size-h6: ceil(($font-size-base * 0.85)) // ~12px
|
||||
|
||||
//* Unit-less `line-height` for use in components like buttons.
|
||||
// $line-height-base: 1.428571429 // 20/14
|
||||
//* Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
|
||||
// $line-height-computed: floor(($font-size-base * $line-height-base)) // ~20px
|
||||
|
||||
//* By default, this inherits from the `<body>`.
|
||||
// $headings-font-family: inherit
|
||||
// $headings-font-weight: 500
|
||||
// $headings-line-height: 1.1
|
||||
// $headings-color: inherit
|
||||
|
||||
//== Iconography
|
||||
//
|
||||
//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
|
||||
|
||||
//* Load fonts from this directory.
|
||||
|
||||
// [converter] Asset helpers such as Sprockets and Node.js Mincer do not resolve relative paths
|
||||
// $icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/")
|
||||
|
||||
//* File name for all font files.
|
||||
// $icon-font-name: "glyphicons-halflings-regular"
|
||||
//* Element ID within SVG icon file.
|
||||
// $icon-font-svg-id: "glyphicons_halflingsregular"
|
||||
|
||||
//== Components
|
||||
//
|
||||
//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
|
||||
|
||||
// $padding-base-vertical: 6px
|
||||
// $padding-base-horizontal: 12px
|
||||
|
||||
// $padding-large-vertical: 10px
|
||||
// $padding-large-horizontal: 16px
|
||||
|
||||
// $padding-small-vertical: 5px
|
||||
// $padding-small-horizontal: 10px
|
||||
|
||||
// $padding-xs-vertical: 1px
|
||||
// $padding-xs-horizontal: 5px
|
||||
|
||||
// $line-height-large: 1.33
|
||||
// $line-height-small: 1.5
|
||||
|
||||
// $border-radius-base: 4px
|
||||
// $border-radius-large: 6px
|
||||
// $border-radius-small: 3px
|
||||
|
||||
//* Global color for active items (e.g., navs or dropdowns).
|
||||
// $component-active-color: #fff
|
||||
//* Global background color for active items (e.g., navs or dropdowns).
|
||||
// $component-active-bg: $brand-primary
|
||||
|
||||
//* Width of the `border` for generating carets that indicator dropdowns.
|
||||
// $caret-width-base: 4px
|
||||
//* Carets increase slightly in size for larger components.
|
||||
// $caret-width-large: 5px
|
||||
|
||||
//== Tables
|
||||
//
|
||||
//## Customizes the `.table` component with basic values, each used across all table variations.
|
||||
|
||||
//* Padding for `<th>`s and `<td>`s.
|
||||
// $table-cell-padding: 8px
|
||||
//* Padding for cells in `.table-condensed`.
|
||||
// $table-condensed-cell-padding: 5px
|
||||
|
||||
//* Default background color used for all tables.
|
||||
// $table-bg: transparent
|
||||
//* Background color used for `.table-striped`.
|
||||
// $table-bg-accent: #f9f9f9
|
||||
//* Background color used for `.table-hover`.
|
||||
// $table-bg-hover: #f5f5f5
|
||||
// $table-bg-active: $table-bg-hover
|
||||
|
||||
//* Border color for table and cell borders.
|
||||
// $table-border-color: #ddd
|
||||
|
||||
//== Buttons
|
||||
//
|
||||
//## For each of Bootstrap's buttons, define text, background and border color.
|
||||
|
||||
// $btn-font-weight: normal
|
||||
|
||||
// $btn-default-color: #333
|
||||
// $btn-default-bg: #fff
|
||||
// $btn-default-border: #ccc
|
||||
|
||||
// $btn-primary-color: #fff
|
||||
// $btn-primary-bg: $brand-primary
|
||||
// $btn-primary-border: darken($btn-primary-bg, 5%)
|
||||
|
||||
// $btn-success-color: #fff
|
||||
// $btn-success-bg: $brand-success
|
||||
// $btn-success-border: darken($btn-success-bg, 5%)
|
||||
|
||||
// $btn-info-color: #fff
|
||||
// $btn-info-bg: $brand-info
|
||||
// $btn-info-border: darken($btn-info-bg, 5%)
|
||||
|
||||
// $btn-warning-color: #fff
|
||||
// $btn-warning-bg: $brand-warning
|
||||
// $btn-warning-border: darken($btn-warning-bg, 5%)
|
||||
|
||||
// $btn-danger-color: #fff
|
||||
// $btn-danger-bg: $brand-danger
|
||||
// $btn-danger-border: darken($btn-danger-bg, 5%)
|
||||
|
||||
// $btn-link-disabled-color: $gray-light
|
||||
|
||||
//== Forms
|
||||
//
|
||||
//##
|
||||
|
||||
//* `<input>` background color
|
||||
// $input-bg: #fff
|
||||
//* `<input disabled>` background color
|
||||
// $input-bg-disabled: $gray-lighter
|
||||
|
||||
//* Text color for `<input>`s
|
||||
// $input-color: $gray
|
||||
//* `<input>` border color
|
||||
// $input-border: #ccc
|
||||
//* `<input>` border radius
|
||||
// $input-border-radius: $border-radius-base
|
||||
//* Border color for inputs on focus
|
||||
// $input-border-focus: #66afe9
|
||||
|
||||
//* Placeholder text color
|
||||
// $input-color-placeholder: $gray-light
|
||||
|
||||
//* Default `.form-control` height
|
||||
// $input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2)
|
||||
//* Large `.form-control` height
|
||||
// $input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2)
|
||||
//* Small `.form-control` height
|
||||
// $input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2)
|
||||
|
||||
// $legend-color: $gray-dark
|
||||
// $legend-border-color: #e5e5e5
|
||||
|
||||
//* Background color for textual input addons
|
||||
// $input-group-addon-bg: $gray-lighter
|
||||
//* Border color for textual input addons
|
||||
// $input-group-addon-border-color: $input-border
|
||||
|
||||
//== Dropdowns
|
||||
//
|
||||
//## Dropdown menu container and contents.
|
||||
|
||||
//* Background for the dropdown menu.
|
||||
// $dropdown-bg: #fff
|
||||
//* Dropdown menu `border-color`.
|
||||
// $dropdown-border: rgba(0,0,0,.15)
|
||||
//* Dropdown menu `border-color` **for IE8**.
|
||||
// $dropdown-fallback-border: #ccc
|
||||
//* Divider color for between dropdown items.
|
||||
// $dropdown-divider-bg: #e5e5e5
|
||||
|
||||
//* Dropdown link text color.
|
||||
// $dropdown-link-color: $gray-dark
|
||||
//* Hover color for dropdown links.
|
||||
// $dropdown-link-hover-color: darken($gray-dark, 5%)
|
||||
//* Hover background for dropdown links.
|
||||
// $dropdown-link-hover-bg: #f5f5f5
|
||||
|
||||
//* Active dropdown menu item text color.
|
||||
// $dropdown-link-active-color: $component-active-color
|
||||
//* Active dropdown menu item background color.
|
||||
// $dropdown-link-active-bg: $component-active-bg
|
||||
|
||||
//* Disabled dropdown menu item background color.
|
||||
// $dropdown-link-disabled-color: $gray-light
|
||||
|
||||
//* Text color for headers within dropdown menus.
|
||||
// $dropdown-header-color: $gray-light
|
||||
|
||||
//* Deprecated `$dropdown-caret-color` as of v3.1.0
|
||||
// $dropdown-caret-color: #000
|
||||
|
||||
//-- Z-index master list
|
||||
//
|
||||
// Warning: Avoid customizing these values. They're used for a bird's eye view
|
||||
// of components dependent on the z-axis and are designed to all work together.
|
||||
//
|
||||
// Note: These variables are not generated into the Customizer.
|
||||
|
||||
// $zindex-navbar: 1000
|
||||
// $zindex-dropdown: 1000
|
||||
// $zindex-popover: 1060
|
||||
// $zindex-tooltip: 1070
|
||||
// $zindex-navbar-fixed: 1030
|
||||
// $zindex-modal-background: 1040
|
||||
// $zindex-modal: 1050
|
||||
|
||||
//== Media queries breakpoints
|
||||
//
|
||||
//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
|
||||
|
||||
// Extra small screen / phone
|
||||
//* Deprecated `$screen-xs` as of v3.0.1
|
||||
// $screen-xs: 480px
|
||||
//* Deprecated `$screen-xs-min` as of v3.2.0
|
||||
// $screen-xs-min: $screen-xs
|
||||
//* Deprecated `$screen-phone` as of v3.0.1
|
||||
// $screen-phone: $screen-xs-min
|
||||
|
||||
// Small screen / tablet
|
||||
//* Deprecated `$screen-sm` as of v3.0.1
|
||||
// $screen-sm: 768px
|
||||
// $screen-sm-min: $screen-sm
|
||||
//* Deprecated `$screen-tablet` as of v3.0.1
|
||||
// $screen-tablet: $screen-sm-min
|
||||
|
||||
// Medium screen / desktop
|
||||
//* Deprecated `$screen-md` as of v3.0.1
|
||||
// $screen-md: 992px
|
||||
// $screen-md-min: $screen-md
|
||||
//* Deprecated `$screen-desktop` as of v3.0.1
|
||||
// $screen-desktop: $screen-md-min
|
||||
|
||||
// Large screen / wide desktop
|
||||
//* Deprecated `$screen-lg` as of v3.0.1
|
||||
// $screen-lg: 1200px
|
||||
// $screen-lg-min: $screen-lg
|
||||
//* Deprecated `$screen-lg-desktop` as of v3.0.1
|
||||
// $screen-lg-desktop: $screen-lg-min
|
||||
|
||||
// So media queries don't overlap when required, provide a maximum
|
||||
// $screen-xs-max: ($screen-sm-min - 1)
|
||||
// $screen-sm-max: ($screen-md-min - 1)
|
||||
// $screen-md-max: ($screen-lg-min - 1)
|
||||
|
||||
//== Grid system
|
||||
//
|
||||
//## Define your custom responsive grid.
|
||||
|
||||
//* Number of columns in the grid.
|
||||
// $grid-columns: 12
|
||||
//* Padding between columns. Gets divided in half for the left and right.
|
||||
// $grid-gutter-width: 30px
|
||||
// Navbar collapse
|
||||
//* Point at which the navbar becomes uncollapsed.
|
||||
// $grid-float-breakpoint: $screen-sm-min
|
||||
//* Point at which the navbar begins collapsing.
|
||||
// $grid-float-breakpoint-max: ($grid-float-breakpoint - 1)
|
||||
|
||||
//== Container sizes
|
||||
//
|
||||
//## Define the maximum width of `.container` for different screen sizes.
|
||||
|
||||
// Small screen / tablet
|
||||
// $container-tablet: ((720px + $grid-gutter-width))
|
||||
//* For `$screen-sm-min` and up.
|
||||
// $container-sm: $container-tablet
|
||||
|
||||
// Medium screen / desktop
|
||||
// $container-desktop: ((940px + $grid-gutter-width))
|
||||
//* For `$screen-md-min` and up.
|
||||
// $container-md: $container-desktop
|
||||
|
||||
// Large screen / wide desktop
|
||||
// $container-large-desktop: ((1140px + $grid-gutter-width))
|
||||
//* For `$screen-lg-min` and up.
|
||||
// $container-lg: $container-large-desktop
|
||||
|
||||
//== Navbar
|
||||
//
|
||||
//##
|
||||
|
||||
// Basics of a navbar
|
||||
// $navbar-height: 50px
|
||||
// $navbar-margin-bottom: $line-height-computed
|
||||
$navbar-margin-bottom: 0;
|
||||
// $navbar-border-radius: $border-radius-base
|
||||
// $navbar-padding-horizontal: floor(($grid-gutter-width / 2))
|
||||
// $navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2)
|
||||
// $navbar-collapse-max-height: 340px
|
||||
|
||||
// $navbar-default-color: #777
|
||||
$navbar-default-bg: #f8f8f8;
|
||||
// $navbar-default-border: darken($navbar-default-bg, 6.5%)
|
||||
|
||||
// Navbar links
|
||||
// $navbar-default-link-color: #777
|
||||
// $navbar-default-link-hover-color: #333
|
||||
$navbar-default-link-hover-bg: darken($navbar-default-bg, 10%);
|
||||
// $navbar-default-link-active-color: #555
|
||||
// $navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%)
|
||||
// $navbar-default-link-disabled-color: #ccc
|
||||
// $navbar-default-link-disabled-bg: transparent
|
||||
|
||||
// Navbar brand label
|
||||
// $navbar-default-brand-color: $navbar-default-link-color
|
||||
// $navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%)
|
||||
$navbar-default-brand-hover-bg: $navbar-default-link-hover-bg;
|
||||
|
||||
// Navbar toggle
|
||||
// $navbar-default-toggle-hover-bg: #ddd
|
||||
// $navbar-default-toggle-icon-bar-bg: #888
|
||||
// $navbar-default-toggle-border-color: #ddd
|
||||
|
||||
// Inverted navbar
|
||||
// Reset inverted navbar basics
|
||||
// $navbar-inverse-color: $gray-light
|
||||
// $navbar-inverse-bg: #222
|
||||
// $navbar-inverse-border: darken($navbar-inverse-bg, 10%)
|
||||
|
||||
// Inverted navbar links
|
||||
// $navbar-inverse-link-color: $gray-light
|
||||
// $navbar-inverse-link-hover-color: #fff
|
||||
// $navbar-inverse-link-hover-bg: transparent
|
||||
// $navbar-inverse-link-active-color: $navbar-inverse-link-hover-color
|
||||
// $navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 10%)
|
||||
// $navbar-inverse-link-disabled-color: #444
|
||||
// $navbar-inverse-link-disabled-bg: transparent
|
||||
|
||||
// Inverted navbar brand label
|
||||
// $navbar-inverse-brand-color: $navbar-inverse-link-color
|
||||
// $navbar-inverse-brand-hover-color: #fff
|
||||
// $navbar-inverse-brand-hover-bg: transparent
|
||||
|
||||
// Inverted navbar toggle
|
||||
// $navbar-inverse-toggle-hover-bg: #333
|
||||
// $navbar-inverse-toggle-icon-bar-bg: #fff
|
||||
// $navbar-inverse-toggle-border-color: #333
|
||||
|
||||
//== Navs
|
||||
//
|
||||
//##
|
||||
|
||||
//=== Shared nav styles
|
||||
// $nav-link-padding: 10px 15px
|
||||
// $nav-link-hover-bg: $gray-lighter
|
||||
|
||||
// $nav-disabled-link-color: $gray-light
|
||||
// $nav-disabled-link-hover-color: $gray-light
|
||||
|
||||
// $nav-open-link-hover-color: #fff
|
||||
|
||||
//== Tabs
|
||||
// $nav-tabs-border-color: #ddd
|
||||
|
||||
// $nav-tabs-link-hover-border-color: $gray-lighter
|
||||
|
||||
// $nav-tabs-active-link-hover-bg: $body-bg
|
||||
// $nav-tabs-active-link-hover-color: $gray
|
||||
// $nav-tabs-active-link-hover-border-color: #ddd
|
||||
|
||||
// $nav-tabs-justified-link-border-color: #ddd
|
||||
// $nav-tabs-justified-active-link-border-color: $body-bg
|
||||
|
||||
//== Pills
|
||||
// $nav-pills-border-radius: $border-radius-base
|
||||
// $nav-pills-active-link-hover-bg: $component-active-bg
|
||||
// $nav-pills-active-link-hover-color: $component-active-color
|
||||
|
||||
//== Pagination
|
||||
//
|
||||
//##
|
||||
|
||||
// $pagination-color: $link-color
|
||||
// $pagination-bg: #fff
|
||||
// $pagination-border: #ddd
|
||||
|
||||
// $pagination-hover-color: $link-hover-color
|
||||
// $pagination-hover-bg: $gray-lighter
|
||||
// $pagination-hover-border: #ddd
|
||||
|
||||
// $pagination-active-color: #fff
|
||||
// $pagination-active-bg: $brand-primary
|
||||
// $pagination-active-border: $brand-primary
|
||||
|
||||
// $pagination-disabled-color: $gray-light
|
||||
// $pagination-disabled-bg: #fff
|
||||
// $pagination-disabled-border: #ddd
|
||||
|
||||
//== Pager
|
||||
//
|
||||
//##
|
||||
|
||||
// $pager-bg: $pagination-bg
|
||||
// $pager-border: $pagination-border
|
||||
// $pager-border-radius: 15px
|
||||
|
||||
// $pager-hover-bg: $pagination-hover-bg
|
||||
|
||||
// $pager-active-bg: $pagination-active-bg
|
||||
// $pager-active-color: $pagination-active-color
|
||||
|
||||
// $pager-disabled-color: $pagination-disabled-color
|
||||
|
||||
//== Jumbotron
|
||||
//
|
||||
//##
|
||||
|
||||
// $jumbotron-padding: 30px
|
||||
// $jumbotron-color: inherit
|
||||
// $jumbotron-bg: $gray-lighter
|
||||
// $jumbotron-heading-color: inherit
|
||||
// $jumbotron-font-size: ceil(($font-size-base * 1.5))
|
||||
|
||||
//== Form states and alerts
|
||||
//
|
||||
//## Define colors for form feedback states and, by default, alerts.
|
||||
|
||||
// $state-success-text: #3c763d
|
||||
// $state-success-bg: #dff0d8
|
||||
// $state-success-border: darken(adjust-hue($state-success-bg, -10), 5%)
|
||||
|
||||
// $state-info-text: #31708f
|
||||
// $state-info-bg: #d9edf7
|
||||
// $state-info-border: darken(adjust-hue($state-info-bg, -10), 7%)
|
||||
|
||||
// $state-warning-text: #8a6d3b
|
||||
// $state-warning-bg: #fcf8e3
|
||||
// $state-warning-border: darken(adjust-hue($state-warning-bg, -10), 5%)
|
||||
|
||||
// $state-danger-text: #a94442
|
||||
// $state-danger-bg: #f2dede
|
||||
// $state-danger-border: darken(adjust-hue($state-danger-bg, -10), 5%)
|
||||
|
||||
//== Tooltips
|
||||
//
|
||||
//##
|
||||
|
||||
//* Tooltip max width
|
||||
// $tooltip-max-width: 200px
|
||||
//* Tooltip text color
|
||||
// $tooltip-color: #fff
|
||||
//* Tooltip background color
|
||||
// $tooltip-bg: #000
|
||||
// $tooltip-opacity: .9
|
||||
|
||||
//* Tooltip arrow width
|
||||
// $tooltip-arrow-width: 5px
|
||||
//* Tooltip arrow color
|
||||
// $tooltip-arrow-color: $tooltip-bg
|
||||
|
||||
//== Popovers
|
||||
//
|
||||
//##
|
||||
|
||||
//* Popover body background color
|
||||
// $popover-bg: #fff
|
||||
//* Popover maximum width
|
||||
// $popover-max-width: 276px
|
||||
//* Popover border color
|
||||
// $popover-border-color: rgba(0,0,0,.2)
|
||||
//* Popover fallback border color
|
||||
// $popover-fallback-border-color: #ccc
|
||||
|
||||
//* Popover title background color
|
||||
// $popover-title-bg: darken($popover-bg, 3%)
|
||||
|
||||
//* Popover arrow width
|
||||
// $popover-arrow-width: 10px
|
||||
//* Popover arrow color
|
||||
// $popover-arrow-color: #fff
|
||||
|
||||
//* Popover outer arrow width
|
||||
// $popover-arrow-outer-width: ($popover-arrow-width + 1)
|
||||
//* Popover outer arrow color
|
||||
// $popover-arrow-outer-color: fade_in($popover-border-color, 0.05)
|
||||
//* Popover outer arrow fallback color
|
||||
// $popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%)
|
||||
|
||||
//== Labels
|
||||
//
|
||||
//##
|
||||
|
||||
//* Default label background color
|
||||
// $label-default-bg: $gray-light
|
||||
//* Primary label background color
|
||||
// $label-primary-bg: $brand-primary
|
||||
//* Success label background color
|
||||
// $label-success-bg: $brand-success
|
||||
//* Info label background color
|
||||
// $label-info-bg: $brand-info
|
||||
//* Warning label background color
|
||||
// $label-warning-bg: $brand-warning
|
||||
//* Danger label background color
|
||||
// $label-danger-bg: $brand-danger
|
||||
|
||||
//* Default label text color
|
||||
// $label-color: #fff
|
||||
//* Default text color of a linked label
|
||||
// $label-link-hover-color: #fff
|
||||
|
||||
//== Modals
|
||||
//
|
||||
//##
|
||||
|
||||
//* Padding applied to the modal body
|
||||
// $modal-inner-padding: 15px
|
||||
|
||||
//* Padding applied to the modal title
|
||||
// $modal-title-padding: 15px
|
||||
//* Modal title line-height
|
||||
// $modal-title-line-height: $line-height-base
|
||||
|
||||
//* Background color of modal content area
|
||||
// $modal-content-bg: #fff
|
||||
//* Modal content border color
|
||||
// $modal-content-border-color: rgba(0,0,0,.2)
|
||||
//* Modal content border color **for IE8**
|
||||
// $modal-content-fallback-border-color: #999
|
||||
|
||||
//* Modal backdrop background color
|
||||
// $modal-backdrop-bg: #000
|
||||
//* Modal backdrop opacity
|
||||
// $modal-backdrop-opacity: .5
|
||||
//* Modal header border color
|
||||
// $modal-header-border-color: #e5e5e5
|
||||
//* Modal footer border color
|
||||
// $modal-footer-border-color: $modal-header-border-color
|
||||
|
||||
// $modal-lg: 900px
|
||||
// $modal-md: 600px
|
||||
// $modal-sm: 300px
|
||||
|
||||
//== Alerts
|
||||
//
|
||||
//## Define alert colors, border radius, and padding.
|
||||
|
||||
// $alert-padding: 15px
|
||||
// $alert-border-radius: $border-radius-base
|
||||
// $alert-link-font-weight: bold
|
||||
|
||||
// $alert-success-bg: $state-success-bg
|
||||
// $alert-success-text: $state-success-text
|
||||
// $alert-success-border: $state-success-border
|
||||
|
||||
// $alert-info-bg: $state-info-bg
|
||||
// $alert-info-text: $state-info-text
|
||||
// $alert-info-border: $state-info-border
|
||||
|
||||
// $alert-warning-bg: $state-warning-bg
|
||||
// $alert-warning-text: $state-warning-text
|
||||
// $alert-warning-border: $state-warning-border
|
||||
|
||||
// $alert-danger-bg: $state-danger-bg
|
||||
// $alert-danger-text: $state-danger-text
|
||||
// $alert-danger-border: $state-danger-border
|
||||
|
||||
//== Progress bars
|
||||
//
|
||||
//##
|
||||
|
||||
//* Background color of the whole progress component
|
||||
// $progress-bg: #f5f5f5
|
||||
//* Progress bar text color
|
||||
// $progress-bar-color: #fff
|
||||
|
||||
//* Default progress bar color
|
||||
// $progress-bar-bg: $brand-primary
|
||||
//* Success progress bar color
|
||||
// $progress-bar-success-bg: $brand-success
|
||||
//* Warning progress bar color
|
||||
// $progress-bar-warning-bg: $brand-warning
|
||||
//* Danger progress bar color
|
||||
// $progress-bar-danger-bg: $brand-danger
|
||||
//* Info progress bar color
|
||||
// $progress-bar-info-bg: $brand-info
|
||||
|
||||
//== List group
|
||||
//
|
||||
//##
|
||||
|
||||
//* Background color on `.list-group-item`
|
||||
// $list-group-bg: #fff
|
||||
//* `.list-group-item` border color
|
||||
// $list-group-border: #ddd
|
||||
//* List group border radius
|
||||
// $list-group-border-radius: $border-radius-base
|
||||
|
||||
//* Background color of single list items on hover
|
||||
// $list-group-hover-bg: #f5f5f5
|
||||
//* Text color of active list items
|
||||
// $list-group-active-color: $component-active-color
|
||||
//* Background color of active list items
|
||||
// $list-group-active-bg: $component-active-bg
|
||||
//* Border color of active list elements
|
||||
// $list-group-active-border: $list-group-active-bg
|
||||
//* Text color for content within active list items
|
||||
// $list-group-active-text-color: lighten($list-group-active-bg, 40%)
|
||||
|
||||
//* Text color of disabled list items
|
||||
// $list-group-disabled-color: $gray-light
|
||||
//* Background color of disabled list items
|
||||
// $list-group-disabled-bg: $gray-lighter
|
||||
//* Text color for content within disabled list items
|
||||
// $list-group-disabled-text-color: $list-group-disabled-color
|
||||
|
||||
// $list-group-link-color: #555
|
||||
// $list-group-link-hover-color: $list-group-link-color
|
||||
// $list-group-link-heading-color: #333
|
||||
|
||||
//== Panels
|
||||
//
|
||||
//##
|
||||
|
||||
// $panel-bg: #fff
|
||||
// $panel-body-padding: 15px
|
||||
// $panel-heading-padding: 10px 15px
|
||||
// $panel-footer-padding: $panel-heading-padding
|
||||
// $panel-border-radius: $border-radius-base
|
||||
|
||||
//* Border color for elements within panels
|
||||
// $panel-inner-border: #ddd
|
||||
// $panel-footer-bg: #f5f5f5
|
||||
|
||||
// $panel-default-text: $gray-dark
|
||||
// $panel-default-border: #ddd
|
||||
// $panel-default-heading-bg: #f5f5f5
|
||||
|
||||
// $panel-primary-text: #fff
|
||||
// $panel-primary-border: $brand-primary
|
||||
// $panel-primary-heading-bg: $brand-primary
|
||||
|
||||
// $panel-success-text: $state-success-text
|
||||
// $panel-success-border: $state-success-border
|
||||
// $panel-success-heading-bg: $state-success-bg
|
||||
|
||||
// $panel-info-text: $state-info-text
|
||||
// $panel-info-border: $state-info-border
|
||||
// $panel-info-heading-bg: $state-info-bg
|
||||
|
||||
// $panel-warning-text: $state-warning-text
|
||||
// $panel-warning-border: $state-warning-border
|
||||
// $panel-warning-heading-bg: $state-warning-bg
|
||||
|
||||
// $panel-danger-text: $state-danger-text
|
||||
// $panel-danger-border: $state-danger-border
|
||||
// $panel-danger-heading-bg: $state-danger-bg
|
||||
|
||||
//== Thumbnails
|
||||
//
|
||||
//##
|
||||
|
||||
//* Padding around the thumbnail image
|
||||
// $thumbnail-padding: 4px
|
||||
//* Thumbnail background color
|
||||
// $thumbnail-bg: $body-bg
|
||||
//* Thumbnail border color
|
||||
// $thumbnail-border: #ddd
|
||||
//* Thumbnail border radius
|
||||
// $thumbnail-border-radius: $border-radius-base
|
||||
|
||||
//* Custom text color for thumbnail captions
|
||||
// $thumbnail-caption-color: $text-color
|
||||
//* Padding around the thumbnail caption
|
||||
// $thumbnail-caption-padding: 9px
|
||||
|
||||
//== Wells
|
||||
//
|
||||
//##
|
||||
|
||||
// $well-bg: #f5f5f5
|
||||
// $well-border: darken($well-bg, 7%)
|
||||
|
||||
//== Badges
|
||||
//
|
||||
//##
|
||||
|
||||
// $badge-color: #fff
|
||||
//* Linked badge text color on hover
|
||||
// $badge-link-hover-color: #fff
|
||||
// $badge-bg: $gray-light
|
||||
|
||||
//* Badge text color in active nav link
|
||||
// $badge-active-color: $link-color
|
||||
//* Badge background color in active nav link
|
||||
// $badge-active-bg: #fff
|
||||
|
||||
// $badge-font-weight: bold
|
||||
// $badge-line-height: 1
|
||||
// $badge-border-radius: 10px
|
||||
|
||||
//== Breadcrumbs
|
||||
//
|
||||
//##
|
||||
|
||||
// $breadcrumb-padding-vertical: 8px
|
||||
// $breadcrumb-padding-horizontal: 15px
|
||||
//* Breadcrumb background color
|
||||
// $breadcrumb-bg: #f5f5f5
|
||||
//* Breadcrumb text color
|
||||
// $breadcrumb-color: #ccc
|
||||
//* Text color of current page in the breadcrumb
|
||||
// $breadcrumb-active-color: $gray-light
|
||||
//* Textual separator for between breadcrumb elements
|
||||
// $breadcrumb-separator: "/"
|
||||
|
||||
//== Carousel
|
||||
//
|
||||
//##
|
||||
|
||||
// $carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6)
|
||||
|
||||
// $carousel-control-color: #fff
|
||||
// $carousel-control-width: 15%
|
||||
// $carousel-control-opacity: .5
|
||||
// $carousel-control-font-size: 20px
|
||||
|
||||
// $carousel-indicator-active-bg: #fff
|
||||
// $carousel-indicator-border-color: #fff
|
||||
|
||||
// $carousel-caption-color: #fff
|
||||
|
||||
//== Close
|
||||
//
|
||||
//##
|
||||
|
||||
// $close-font-weight: bold
|
||||
// $close-color: #000
|
||||
// $close-text-shadow: 0 1px 0 #fff
|
||||
|
||||
//== Code
|
||||
//
|
||||
//##
|
||||
|
||||
// $code-color: #c7254e
|
||||
// $code-bg: #f9f2f4
|
||||
|
||||
// $kbd-color: #fff
|
||||
// $kbd-bg: #333
|
||||
|
||||
// $pre-bg: #f5f5f5
|
||||
// $pre-color: $gray-dark
|
||||
// $pre-border-color: #ccc
|
||||
// $pre-scrollable-max-height: 340px
|
||||
|
||||
//== Type
|
||||
//
|
||||
//##
|
||||
|
||||
//* Horizontal offset for forms and lists.
|
||||
// $component-offset-horizontal: 180px
|
||||
//* Text muted color
|
||||
// $text-muted: $gray-light
|
||||
//* Abbreviations and acronyms border color
|
||||
// $abbr-border-color: $gray-light
|
||||
//* Headings small color
|
||||
// $headings-small-color: $gray-light
|
||||
//* Blockquote small color
|
||||
// $blockquote-small-color: $gray-light
|
||||
//* Blockquote font size
|
||||
// $blockquote-font-size: ($font-size-base * 1.25)
|
||||
//* Blockquote border color
|
||||
// $blockquote-border-color: $gray-lighter
|
||||
//* Page header border color
|
||||
// $page-header-border-color: $gray-lighter
|
||||
//* Width of horizontal description list titles
|
||||
// $dl-horizontal-offset: $component-offset-horizontal
|
||||
//* Horizontal line color.
|
||||
// $hr-border: $gray-lighter
|
@ -1,188 +0,0 @@
|
||||
@import "bootstrap-compass";
|
||||
@import "bootstrap-variables";
|
||||
@import "bootstrap";
|
||||
|
||||
$sidebar-width: 200px;
|
||||
$content-background: white;
|
||||
$sidebar-background: #eee;
|
||||
|
||||
html, body {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
padding-top: 50px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#lower-wrapper {
|
||||
min-height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#content {
|
||||
height: 100%;
|
||||
padding: 1em;
|
||||
|
||||
margin-left: $sidebar-width;
|
||||
background: $content-background;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: $sidebar-width;
|
||||
background: $sidebar-background;
|
||||
height: 100%;
|
||||
|
||||
padding: 5px;
|
||||
|
||||
.panel-heading {
|
||||
padding: 3px 5px;
|
||||
|
||||
.panel-title {
|
||||
font-size: 12px;
|
||||
font-weight: 200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navbar {
|
||||
margin-top: -50px;
|
||||
}
|
||||
|
||||
img {
|
||||
box-shadow: 2px 2px 5px gray;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAAXNSR0IArs4c6QAAAAJiS0dEAP+Hj8y/AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAB3RJTUUH3gUBEi4DGRAQYgAAAB1JREFUGNNjfMoAAVJQmokBDdBHgPE/lPFsYN0BABdaAwN6tehMAAAAAElFTkSuQmCC");
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.waiting, .waiting * {
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
.iframe textarea {
|
||||
resize: none;
|
||||
}
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
code {
|
||||
color: green;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tries {
|
||||
margin: 1em;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#tryHistory {
|
||||
position: absolute;
|
||||
top: 3em;
|
||||
right: 10px;
|
||||
width: 75px;
|
||||
|
||||
.tries {
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
|
||||
#chooseList {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.show {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.image-wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#chooseSource {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#selectedSource {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#sourceCode {
|
||||
display: none;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#gitInfo {
|
||||
font-size: 70%;
|
||||
}
|
||||
|
||||
#output-wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.compile-error {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* CodeMirror customization */
|
||||
|
||||
.CodeMirror .error {
|
||||
background: #f88;
|
||||
}
|
||||
|
||||
.CodeMirror-lines,
|
||||
.CodeMirror-scroll
|
||||
{
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
border: solid gray 1px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Make the code editor automatically resize */
|
||||
|
||||
.CodeMirror-scroll {
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
/* Twitter Bootstrap customization */
|
||||
|
||||
.navbar {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
padding: 0;
|
||||
|
||||
img {
|
||||
height: 50px;
|
||||
box-shadow: none;
|
||||
background: none;
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
#include "SkCanvas.h"
|
||||
#include "SkData.h"
|
||||
#include "SkForceLinking.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkImageEncoder.h"
|
||||
#include "SkImageInfo.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkSurface.h"
|
||||
|
||||
SkBitmap source;
|
||||
|
||||
void draw(SkCanvas* canvas) {
|
||||
#line 1
|
||||
SkPaint p;
|
||||
#line 2
|
||||
p.setColor(SK_ColorRED);
|
||||
#line 3
|
||||
p.setAntiAlias(true);
|
||||
#line 4
|
||||
p.setStyle(SkPaint::kStroke_Style);
|
||||
#line 5
|
||||
p.setStrokeWidth(10);
|
||||
#line 6
|
||||
|
||||
#line 7
|
||||
canvas->drawLine(20, 20, 100, 100, p);
|
||||
#line 8
|
||||
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Limit the amount of time and the core size for the compiler.
|
||||
set -e
|
||||
|
||||
ulimit -t 5 -c 0
|
||||
|
||||
cc $@
|
@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Limit the amount of time and the core size for the compiler.
|
||||
set -e
|
||||
|
||||
ulimit -t 5 -c 0
|
||||
|
||||
c++ $@
|
@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# fiddle_gyp will copy the fiddle-specific gyp file from the cache
|
||||
# into the local skia tree, and generate the necessary ninja build
|
||||
# files.
|
||||
#
|
||||
# Because gyp is really picky about directory structures, this is
|
||||
# necessary to avoid re-building the entire skia library every time.
|
||||
|
||||
[ -z "$SKIA_ROOT" ] && SKIA_ROOT="../../../"
|
||||
[ -z "$WEBTRY_CACHE_DIR" ] && WEBTRY_CACHE_DIR="../../../../cache"
|
||||
|
||||
cp $WEBTRY_CACHE_DIR/$1.gyp $SKIA_ROOT/gyp
|
||||
(cd $SKIA_ROOT ; ./gyp_skia gyp/$1.gyp gyp/most.gyp -Dskia_mesa=1)
|
@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# fiddle_ninja simply builds a Release version of the
|
||||
# provided fiddle into the local skia tree's out/Release
|
||||
# directory.
|
||||
#
|
||||
# This script must be run after fiddle_gyp
|
||||
|
||||
[ -z $SKIA_ROOT ] && SKIA_ROOT="/skia_build/skia"
|
||||
|
||||
PATH=$PATH:/skia_build/depot_tools
|
||||
|
||||
ninja -C $SKIA_ROOT/out/Release $1
|
||||
|
@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# fiddle_run executes the build fiddle (from the local
|
||||
# skia tree's out/Release directory) and places the output
|
||||
# png into the inout directory so it can be seen
|
||||
# outside the chroot jail and served back to the user.
|
||||
|
||||
[ -z $SKIA_ROOT ] && SKIA_ROOT="/skia_build/skia"
|
||||
[ -z $WEBTRY_INOUT ] && WEBTRY_INOUT="/skia_build/inout"
|
||||
|
||||
$SKIA_ROOT/out/Release/$1 --out $WEBTRY_INOUT/$1 "${@:2}"
|
@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# fiddle_wrapper takes the hash of the fiddle as its first argument, and additional arguments to
|
||||
# be passed to the build fiddle executable. Then it:
|
||||
#
|
||||
# 1) runs fiddle_gyp to create the gyp file
|
||||
# 2) runs fiddle_ninja to build the executable
|
||||
# 3) runs fiddle_run to generate the output .png file.
|
||||
#
|
||||
# the output PNG file goes into the inout directory, which is shared between the chroot
|
||||
# jail and the webserver environment.
|
||||
|
||||
[ -z "$SKIA_ROOT" ] && SKIA_ROOT="/skia_build/skia"
|
||||
|
||||
cd $SKIA_ROOT/experimental/webtry/scripts
|
||||
|
||||
./fiddle_gyp $1
|
||||
./fiddle_ninja $1
|
||||
./fiddle_run $@
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* seccomp example for x86 (32-bit and 64-bit) with BPF macros
|
||||
*
|
||||
* Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
|
||||
* Authors:
|
||||
* Will Drewry <wad@chromium.org>
|
||||
* Kees Cook <keescook@chromium.org>
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
* A stripped down version of the file found in this tutorial: http://outflux.net/teach-seccomp/.
|
||||
*/
|
||||
#ifndef _SECCOMP_BPF_H_
|
||||
#define _SECCOMP_BPF_H_
|
||||
|
||||
#ifndef SK_UNSAFE_BUILD_DESKTOP_ONLY
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/prctl.h>
|
||||
#ifndef PR_SET_NO_NEW_PRIVS
|
||||
# define PR_SET_NO_NEW_PRIVS 38
|
||||
#endif
|
||||
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/filter.h>
|
||||
#ifdef HAVE_LINUX_SECCOMP_H
|
||||
# include <linux/seccomp.h>
|
||||
#endif
|
||||
#ifndef SECCOMP_MODE_FILTER
|
||||
# define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
|
||||
# define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
|
||||
# define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
|
||||
# define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
|
||||
struct seccomp_data {
|
||||
int nr;
|
||||
__u32 arch;
|
||||
__u64 instruction_pointer;
|
||||
__u64 args[6];
|
||||
};
|
||||
#endif
|
||||
#ifndef SYS_SECCOMP
|
||||
# define SYS_SECCOMP 1
|
||||
#endif
|
||||
|
||||
#define syscall_nr (offsetof(struct seccomp_data, nr))
|
||||
|
||||
#define EXAMINE_SYSCALL \
|
||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr)
|
||||
|
||||
#define ALLOW_SYSCALL(name) \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##name, 0, 1), \
|
||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
|
||||
|
||||
#define KILL_PROCESS \
|
||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
|
||||
|
||||
#endif /* SK_UNSAFE_BUILD_DESKTOP_ONLY */
|
||||
|
||||
#endif /* _SECCOMP_BPF_H_ */
|
@ -1,45 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# The continue_install script updates the webtry user's copy of skia and depot_tools.
|
||||
# It then builds the webtry server outside the jail.
|
||||
#
|
||||
# The setup scripts should run this script as the 'webtry' user.
|
||||
#
|
||||
# See the README file for detailed installation instructions.
|
||||
|
||||
# Install Go
|
||||
|
||||
cd
|
||||
|
||||
if [ -d go ]; then
|
||||
echo Go already installed.
|
||||
else
|
||||
wget https://storage.googleapis.com/golang/go1.3.3.linux-amd64.tar.gz
|
||||
tar -xzf go1.3.3.linux-amd64.tar.gz
|
||||
fi
|
||||
|
||||
mkdir ${HOME}/golib
|
||||
export GOROOT=${HOME}/go
|
||||
export GOPATH=${HOME}/golib
|
||||
export PATH=$PATH:$GOROOT/bin
|
||||
|
||||
# Install depot_tools.
|
||||
if [ -d depot_tools ]; then
|
||||
(cd depot_tools && git pull);
|
||||
else
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git;
|
||||
fi
|
||||
export PATH=$PATH:~/depot_tools
|
||||
|
||||
# Checkout the skia code and dependencies (again)
|
||||
mkdir skia
|
||||
cd skia
|
||||
gclient config --name . https://skia.googlesource.com/skia.git
|
||||
gclient sync
|
||||
git checkout master
|
||||
|
||||
cd experimental/webtry
|
||||
|
||||
go get -u skia.googlesource.com/buildbot.git/perf/go/logserver
|
||||
go get -d
|
||||
./build
|
@ -1,41 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# this script runs as root inside the chroot environment and updates the depot tools, go environment,
|
||||
# and skia source.
|
||||
|
||||
# need to mount /dev/shm first so that python will execute properly.
|
||||
|
||||
mount /dev/shm
|
||||
|
||||
SKIA_BUILD=/skia_build
|
||||
cd ${SKIA_BUILD}
|
||||
|
||||
# Install depot_tools.
|
||||
if [ -d depot_tools ]; then
|
||||
(cd depot_tools && git pull);
|
||||
else
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git;
|
||||
fi
|
||||
export PATH=$PATH:${SKIA_BUILD}/depot_tools
|
||||
|
||||
# Sometimes you need to test patches on the server, to do that uncomment
|
||||
# the following commented out lines and update the PATCH env variable to the
|
||||
# name of the codereview to use.
|
||||
|
||||
# rm -rf skia
|
||||
|
||||
# Checkout the skia code and dependencies.
|
||||
mkdir skia
|
||||
cd skia
|
||||
gclient config --name . https://skia.googlesource.com/skia.git
|
||||
gclient sync
|
||||
git checkout master
|
||||
|
||||
# PATCH=issue196723021_100001.diff
|
||||
# rm $PATCH
|
||||
# wget https://codereview.chromium.org/download/$PATCH
|
||||
# git apply $PATCH
|
||||
|
||||
SKIA_GYP_OUTPUT_DIR=${SKIA_BUILD}/skia/out GYP_GENERATORS=ninja ./gyp_skia -Dskia_mesa=1
|
||||
|
||||
ninja -C ${SKIA_BUILD}/skia/out/Release skia_lib libjpeg libSkKTX libetc1 flags sk_tool_utils resources
|
@ -1,8 +0,0 @@
|
||||
apt-get install -y g++ libfreetype6 libfreetype6-dev libpng12-0 libpng12-dev \
|
||||
libglu1-mesa-dev mesa-common-dev freeglut3-dev libgif-dev libfontconfig \
|
||||
libfontconfig-dev git python wget libpoppler-cpp-dev libosmesa6-dev
|
||||
|
||||
mkdir /skia_build
|
||||
chmod 777 /skia_build
|
||||
|
||||
mkdir /skia_build/bin
|
@ -1,159 +0,0 @@
|
||||
#! /bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: logserver
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Start logserver.
|
||||
# Description: Serves the log file directory via HTTP.
|
||||
### END INIT INFO
|
||||
|
||||
# Author: Joe Gregorio <jcgregorio@google.com>
|
||||
#
|
||||
# Copied from /etc/init.d/skeleton and modified only the following
|
||||
# environment variables and updated the start-stop-daemon calls
|
||||
# in do_start() to add --make-pidfile, --background, and --chuid.
|
||||
|
||||
# Do NOT "set -e"
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
DESC="The Skia WebTry log server application."
|
||||
NAME=logserver
|
||||
DAEMON=/home/webtry/golib/bin/$NAME
|
||||
DAEMON_ARGS="--log_dir=/tmp/glog"
|
||||
PIDFILE=/var/run/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x "$DAEMON" ] || exit 0
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||
|
||||
# Load the VERBOSE setting and other rcS variables
|
||||
. /lib/init/vars.sh
|
||||
|
||||
# Define LSB log_* functions.
|
||||
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
|
||||
# and status_of_proc is working.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service
|
||||
#
|
||||
do_start()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
start-stop-daemon --start --pidfile $PIDFILE --exec $DAEMON --make-pidfile --background --chuid webtry --test > /dev/null \
|
||||
|| return 1
|
||||
start-stop-daemon --start --pidfile $PIDFILE --exec $DAEMON --make-pidfile --background --chuid webtry --exec $DAEMON -- \
|
||||
$DAEMON_ARGS \
|
||||
|| return 2
|
||||
# Add code here, if necessary, that waits for the process to be ready
|
||||
# to handle requests from services started subsequently which depend
|
||||
# on this one. As a last resort, sleep for some time.
|
||||
}
|
||||
|
||||
#
|
||||
# Function that stops the daemon/service
|
||||
#
|
||||
do_stop()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been stopped
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
|
||||
RETVAL="$?"
|
||||
[ "$RETVAL" = 2 ] && return 2
|
||||
# Wait for children to finish too if this is a daemon that forks
|
||||
# and if the daemon is only ever run from this initscript.
|
||||
# If the above conditions are not satisfied then add some other code
|
||||
# that waits for the process to drop all resources that could be
|
||||
# needed by services started subsequently. A last resort is to
|
||||
# sleep for some time.
|
||||
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
|
||||
[ "$?" = 2 ] && return 2
|
||||
# Many daemons don't delete their pidfiles when they exit.
|
||||
rm -f $PIDFILE
|
||||
return "$RETVAL"
|
||||
}
|
||||
|
||||
#
|
||||
# Function that sends a SIGHUP to the daemon/service
|
||||
#
|
||||
do_reload() {
|
||||
#
|
||||
# If the daemon can reload its configuration without
|
||||
# restarting (for example, when it is sent a SIGHUP),
|
||||
# then implement that here.
|
||||
#
|
||||
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
|
||||
return 0
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
||||
do_start
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
stop)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
status)
|
||||
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
|
||||
;;
|
||||
#reload|force-reload)
|
||||
#
|
||||
# If do_reload() is not implemented then leave this commented out
|
||||
# and leave 'force-reload' as an alias for 'restart'.
|
||||
#
|
||||
#log_daemon_msg "Reloading $DESC" "$NAME"
|
||||
#do_reload
|
||||
#log_end_msg $?
|
||||
#;;
|
||||
restart|force-reload)
|
||||
#
|
||||
# If the "reload" option is implemented then remove the
|
||||
# 'force-reload' alias
|
||||
#
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1)
|
||||
do_start
|
||||
case "$?" in
|
||||
0) log_end_msg 0 ;;
|
||||
1) log_end_msg 1 ;; # Old process is still running
|
||||
*) log_end_msg 1 ;; # Failed to start
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
# Failed to stop
|
||||
log_end_msg 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
:
|
@ -1,159 +0,0 @@
|
||||
#! /bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: webtry
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Start webtry.
|
||||
# Description: Web server for trying Skia C++ code.
|
||||
### END INIT INFO
|
||||
|
||||
# Author: Joe Gregorio <jcgregorio@google.com>
|
||||
#
|
||||
# Copied from /etc/init.d/skeleton and modified only the following
|
||||
# environment variables and updated the start-stop-daemon calls
|
||||
# in do_start() to add --make-pidfile, --background, and --chuid.
|
||||
|
||||
# Do NOT "set -e"
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
DESC="The Skia webtry application."
|
||||
NAME=webtry
|
||||
DAEMON=/home/webtry/skia/experimental/webtry/$NAME
|
||||
DAEMON_ARGS="--use_chroot --log_dir=/tmp/glog"
|
||||
PIDFILE=/var/run/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x "$DAEMON" ] || exit 0
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||
|
||||
# Load the VERBOSE setting and other rcS variables
|
||||
. /lib/init/vars.sh
|
||||
|
||||
# Define LSB log_* functions.
|
||||
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
|
||||
# and status_of_proc is working.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service
|
||||
#
|
||||
do_start()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
start-stop-daemon --start --pidfile $PIDFILE --exec $DAEMON --make-pidfile --background --chuid webtry --test > /dev/null \
|
||||
|| return 1
|
||||
start-stop-daemon --start --pidfile $PIDFILE --exec $DAEMON --make-pidfile --background --chuid webtry --exec $DAEMON -- \
|
||||
$DAEMON_ARGS \
|
||||
|| return 2
|
||||
# Add code here, if necessary, that waits for the process to be ready
|
||||
# to handle requests from services started subsequently which depend
|
||||
# on this one. As a last resort, sleep for some time.
|
||||
}
|
||||
|
||||
#
|
||||
# Function that stops the daemon/service
|
||||
#
|
||||
do_stop()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been stopped
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
|
||||
RETVAL="$?"
|
||||
[ "$RETVAL" = 2 ] && return 2
|
||||
# Wait for children to finish too if this is a daemon that forks
|
||||
# and if the daemon is only ever run from this initscript.
|
||||
# If the above conditions are not satisfied then add some other code
|
||||
# that waits for the process to drop all resources that could be
|
||||
# needed by services started subsequently. A last resort is to
|
||||
# sleep for some time.
|
||||
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
|
||||
[ "$?" = 2 ] && return 2
|
||||
# Many daemons don't delete their pidfiles when they exit.
|
||||
rm -f $PIDFILE
|
||||
return "$RETVAL"
|
||||
}
|
||||
|
||||
#
|
||||
# Function that sends a SIGHUP to the daemon/service
|
||||
#
|
||||
do_reload() {
|
||||
#
|
||||
# If the daemon can reload its configuration without
|
||||
# restarting (for example, when it is sent a SIGHUP),
|
||||
# then implement that here.
|
||||
#
|
||||
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
|
||||
return 0
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
||||
do_start
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
stop)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
status)
|
||||
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
|
||||
;;
|
||||
#reload|force-reload)
|
||||
#
|
||||
# If do_reload() is not implemented then leave this commented out
|
||||
# and leave 'force-reload' as an alias for 'restart'.
|
||||
#
|
||||
#log_daemon_msg "Reloading $DESC" "$NAME"
|
||||
#do_reload
|
||||
#log_end_msg $?
|
||||
#;;
|
||||
restart|force-reload)
|
||||
#
|
||||
# If the "reload" option is implemented then remove the
|
||||
# 'force-reload' alias
|
||||
#
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1)
|
||||
do_start
|
||||
case "$?" in
|
||||
0) log_end_msg 0 ;;
|
||||
1) log_end_msg 1 ;; # Old process is still running
|
||||
*) log_end_msg 1 ;; # Failed to start
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
# Failed to stop
|
||||
log_end_msg 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
:
|
@ -1,11 +0,0 @@
|
||||
check process webtry with pidfile /var/run/webtry.pid
|
||||
start program = "/etc/init.d/webtry start"
|
||||
stop program = "/etc/init.d/webtry stop"
|
||||
|
||||
check process logserver with pidfile /var/run/logserver.pid
|
||||
start program = "/etc/init.d/logserver start"
|
||||
stop program = "/etc/init.d/logserver stop"
|
||||
|
||||
check process squid3 with pidfile /var/run/squid3.pid
|
||||
start program = "/etc/init.d/squid3 start"
|
||||
stop program = "/etc/init.d/squid3 stop"
|
@ -1,10 +0,0 @@
|
||||
[webtry]
|
||||
description=Chroot jail for webtry runs.
|
||||
type=directory
|
||||
directory=/srv/chroot/webtry_gyp
|
||||
users=default,webtry
|
||||
root-groups=default
|
||||
personality=linux
|
||||
preserve-environment=false
|
||||
profile=minimal
|
||||
union-type=aufs
|
@ -1,6 +0,0 @@
|
||||
http_port 80 accel defaultsite=skfiddle.com
|
||||
cache_peer 127.0.0.1 parent 8000 0 no-query originserver name=myAccel
|
||||
acl our_sites dstdomain skfiddle.com
|
||||
http_access allow our_sites
|
||||
cache_peer_access myAccel allow our_sites
|
||||
cache_peer_access myAccel deny all
|
@ -1,87 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Script to setup a GCE instance to run the webtry server.
|
||||
# For full instructions see the README file.
|
||||
|
||||
function banner {
|
||||
echo ""
|
||||
echo "******************************************"
|
||||
echo "*"
|
||||
echo "* $1"
|
||||
echo "*"
|
||||
echo "******************************************"
|
||||
echo ""
|
||||
}
|
||||
|
||||
banner "Installing debian packages needed for the server"
|
||||
|
||||
sudo apt-get install schroot debootstrap monit squid3
|
||||
|
||||
# although aufs is being replaced by overlayfs, it's not clear
|
||||
# to me if overlayfs is completely supported by schroot yet.
|
||||
sudo apt-get install aufs-tools
|
||||
|
||||
banner "Setting up the webtry user account"
|
||||
sudo adduser webtry
|
||||
|
||||
sudo mkdir /home/webtry/cache
|
||||
sudo mkdir /home/webtry/cache/src
|
||||
sudo mkdir /home/webtry/inout
|
||||
sudo chmod 777 /home/webtry/inout
|
||||
sudo chmod 777 /home/webtry/cache
|
||||
sudo chmod 777 /home/webtry/cache/src
|
||||
|
||||
sudo cp sys/webtry_schroot /etc/schroot/chroot.d/webtry
|
||||
|
||||
CHROOT_JAIL=/srv/chroot/webtry_gyp
|
||||
# Build the chroot environment.
|
||||
if [ ! -d ${CHROOT_JAIL} ]; then
|
||||
banner "Building the chroot jail"
|
||||
sudo mkdir -p ${CHROOT_JAIL}
|
||||
|
||||
sudo debootstrap --variant=minbase wheezy ${CHROOT_JAIL}
|
||||
sudo cp setup_jail.sh ${CHROOT_JAIL}/bin
|
||||
sudo chmod 755 ${CHROOT_JAIL}/bin/setup_jail.sh
|
||||
sudo chroot ${CHROOT_JAIL} /bin/setup_jail.sh
|
||||
sudo sh -c "echo 'none /dev/shm tmpfs rw,nosuid,nodev,noexec 0 0' >> ${CHROOT_JAIL}/etc/fstab"
|
||||
fi
|
||||
|
||||
# The continue_install_jail script will update and build up the skia library
|
||||
# inside the jail.
|
||||
|
||||
banner "Installing and updating software on the chroot jail"
|
||||
sudo cp continue_install_jail.sh ${CHROOT_JAIL}/bin/continue_install_jail.sh
|
||||
sudo chmod 755 ${CHROOT_JAIL}/bin/continue_install_jail.sh
|
||||
sudo chroot ${CHROOT_JAIL} /bin/continue_install_jail.sh
|
||||
sudo chown -R webtry:webtry ${CHROOT_JAIL}/skia_build/skia
|
||||
|
||||
# The continue_install script will fetch the latest versions of
|
||||
# skia and depot_tools. We split up the installation process into
|
||||
# two pieces like this so that the continue_install script can
|
||||
# be run independently of this one to fetch and build the latest skia.
|
||||
|
||||
banner "Building the webtry server outside the jail"
|
||||
|
||||
sudo cp continue_install.sh /home/webtry
|
||||
sudo chown webtry:webtry /home/webtry/continue_install.sh
|
||||
sudo su - webtry -c /home/webtry/continue_install.sh
|
||||
|
||||
banner "Setting up system initialization scripts"
|
||||
|
||||
sudo cp sys/webtry_init /etc/init.d/webtry
|
||||
sudo cp sys/logserver_init /etc/init.d/logserver
|
||||
sudo cp sys/webtry_monit /etc/monit/conf.d/webtry
|
||||
sudo cp sys/webtry_squid /etc/squid3/squid.conf
|
||||
sudo chmod 744 /etc/init.d/webtry
|
||||
sudo chmod 744 /etc/init.d/logserver
|
||||
|
||||
# Confirm that monit is happy.
|
||||
sudo monit -t
|
||||
sudo monit reload
|
||||
|
||||
banner "Restarting webtry server"
|
||||
|
||||
sudo /etc/init.d/webtry restart
|
||||
sudo /etc/init.d/logserver restart
|
||||
|
||||
banner "All done!"
|
@ -1,83 +0,0 @@
|
||||
<section id="content">
|
||||
|
||||
<template id="sourcesTemplate">
|
||||
<button id="" class=source><img width=64 height=64 src=""></button>
|
||||
</template>
|
||||
|
||||
<div id="inputBitmapEnable">
|
||||
<input type="checkbox" id="enableSource" data-id="{{.Source}}">
|
||||
<label for="enableSource">Use an input bitmap</label>
|
||||
</div>
|
||||
|
||||
<button id="selectedSource"></button>
|
||||
|
||||
<pre id="sourceCode">SkBitmap source;</pre>
|
||||
|
||||
<div class="well" id="chooseSource">
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
Choose an existing image to use as an input bitmap, or upload a new one below.
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body" id="chooseList">
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="panel-title">
|
||||
Upload a new image
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="/sources/" method="post" accept-charset="utf-8" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="upload">File input</label>
|
||||
<input type="file" accept="image/*" name="upload" value="" id="upload">
|
||||
</div>
|
||||
<button class="btn btn-default" type="submit">Upload Image</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<textarea spellcheck=false name='code' id='code' rows='15' cols='100'>{{.Code}}</textarea>
|
||||
|
||||
<div class="action-buttons">
|
||||
<button class="btn btn-primary btn-lg" id='run'>Run</button>
|
||||
<a class="btn btn-default btn-lg" href='{{if .Hash}}/c/{{.Hash}}{{end}}' {{if not .Hash}}style="display: none;"{{end}} target=_blank id="permalink">Share</a>
|
||||
|
||||
<button class="btn btn-default btn-lg" id='embedButton' {{if not .Hash}}style="display:none;"{{end}}/>Embed</button>
|
||||
<input type="text" value="" id="embed" readonly style="display:none;">
|
||||
</div>
|
||||
|
||||
<div id="raster-output" class="image-wrapper panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
Raster Output
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<img touch-action='none' class='zoom' id='raster-img' onload="onLoadImage(this)" src='{{if .Hash}}/i/{{.Hash}}_raster.png{{end}}'/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="gpu-output" class="image-wrapper panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
Ganesh Output
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<img touch-action='none' class='zoom' id='gpu-img' onload="onLoadImage(this)" src='{{if .Hash}}/i/{{.Hash}}_gpu.png{{end}}'/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p id='zoomHex'></p>
|
||||
|
||||
<div id="output-wrapper">
|
||||
<h2>Build Issues (click errors to jump to that line)</h2>
|
||||
<pre id="output"></pre>
|
||||
</div>
|
||||
|
||||
</section>
|
@ -1,12 +0,0 @@
|
||||
<meta charset='utf-8' />
|
||||
<meta name=viewport content='width=device-width, initial-scale=1'>
|
||||
|
||||
<link rel='stylesheet' href='/res/webtry/css/webtry.css' type='text/css'>
|
||||
<link rel='stylesheet' href='/res/css/cm/codemirror.css' type='text/css'>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
<script src="/res/webtry/js/bootstrap.js"></script>
|
||||
<script src='/res/js/polyfill.js' type='text/javascript'></script>
|
||||
<script src='/res/js/cm/codemirror.js' type='text/javascript'></script>
|
||||
<script src='/res/js/cm/clike.js' type='text/javascript'></script>
|
||||
<script src='/res/js/webtry.js' type='text/javascript'></script>
|
@ -1,16 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Skia WebTry</title>
|
||||
{{template "headercommon.html" .}}
|
||||
<link rel='import' type='text/html' href='/res/imp/zoom.html'>
|
||||
</head>
|
||||
<body class=iframe>
|
||||
{{template "content.html" .}}
|
||||
<script type='text/javascript'>
|
||||
// Not running in a workspace.
|
||||
var workspaceName = '';
|
||||
</script>
|
||||
{{template "footercommon.html" .}}
|
||||
</body>
|
||||
</html>
|
@ -1,23 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Skia WebTry</title>
|
||||
{{template "headercommon.html" .}}
|
||||
<link rel='import' type='text/html' href='/res/imp/zoom.html'>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
{{template "titlebar.html" .}}
|
||||
<div id="lower-wrapper">
|
||||
{{template "sidebar.html" .}}
|
||||
{{template "content.html" .}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type='text/javascript'>
|
||||
// Not running in a workspace.
|
||||
var workspaceName = '';
|
||||
</script>
|
||||
{{template "footercommon.html" .}}
|
||||
</body>
|
||||
</html>
|
@ -1,25 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Recent SkFiddles</title>
|
||||
<meta charset='utf-8' />
|
||||
{{template "headercommon.html" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "titlebar.html" .}}
|
||||
<section id=content>
|
||||
<h1>Recent Activity</h1>
|
||||
<section>
|
||||
{{range .Tries}}
|
||||
<div class=tries>
|
||||
<h2><a href="/c/{{.Hash}}">{{.CreateTS}}</a></h2>
|
||||
<a href="/c/{{.Hash}}">
|
||||
<img width=128 height=128 src="/i/{{.Hash}}.png">
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</section>
|
||||
</section>
|
||||
{{template "footercommon.html" .}}
|
||||
</body>
|
||||
</html>
|
@ -1,54 +0,0 @@
|
||||
<section id="sidebar">
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
Fiddle Options
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<label for="image-width" class="col-sm-4 control-label">Width</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" id="image-width" value="{{.Width}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="image-height" class="col-sm-4 control-label">Height</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" id="image-height" value="{{.Height}}">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
Run Configuration
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form id="run-configuration" class="form-horizontal" role="form">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="use-raster" type="checkbox" value="" checked>
|
||||
Raster
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="use-gpu" type="checkbox" value="">
|
||||
Ganesh
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="use-pdf" type="checkbox" value="" disabled>
|
||||
PDF (coming soon)
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
@ -1,37 +0,0 @@
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'configurations': {
|
||||
'Debug': { },
|
||||
'Release': { }
|
||||
},
|
||||
'cflags!': [
|
||||
'-Werror'
|
||||
],
|
||||
'target_name': '{{.Hash}}',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'skia_lib.gyp:skia_lib',
|
||||
'flags.gyp:flags',
|
||||
'tools.gyp:sk_tool_utils'
|
||||
|
||||
],
|
||||
'include_dirs': [
|
||||
'../include/config',
|
||||
'../include/core',
|
||||
'../include/gpu',
|
||||
'../tools/flags',
|
||||
'../src/core',
|
||||
],
|
||||
'conditions': [
|
||||
['skia_os == "mac"', {
|
||||
'defines': ['SK_UNSAFE_BUILD_DESKTOP_ONLY=1']
|
||||
}]
|
||||
],
|
||||
'sources': [
|
||||
'../../cache/src/{{.Hash}}.cpp',
|
||||
'../experimental/webtry/main.cpp'
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/">
|
||||
<img src="/res/img/skia.png">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="/recent/">Recent</a></li>
|
||||
<li><a href="/w/">Workspace</a></li>
|
||||
<li><a target="_blank" href="http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classes.html">Doxygen</a></li>
|
||||
<li><a target="_blank" href="https://github.com/google/skia/tree/master/experimental/webtry">Code</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a target="_blank" id="gitInfo" href="https://github.com/google/skia/commit/{{.Titlebar.GitHash}}">{{.Titlebar.GitInfo}}</a></li>
|
||||
</ul>
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
@ -1,42 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Workspace</title>
|
||||
{{template "headercommon.html" .}}
|
||||
<link rel='import' type='text/html' href='/res/imp/zoom.html'>
|
||||
</head>
|
||||
<body>
|
||||
<template id="tryTemplate">
|
||||
<div class=tries data-try=''>
|
||||
<img width="64" src=''>
|
||||
</div>
|
||||
</template>
|
||||
<div id="wrapper">
|
||||
{{template "titlebar.html" .}}
|
||||
{{if .Name}}
|
||||
<div id="lower-wrapper">
|
||||
{{template "sidebar.html" .}}
|
||||
{{template "content.html" .}}
|
||||
</div>
|
||||
<section id="tryHistory">
|
||||
</section>
|
||||
|
||||
<script type='text/javascript'>
|
||||
var history_ = {{.Tries}};
|
||||
</script>
|
||||
<script type='text/javascript'>
|
||||
// Set the workspace name so run.js also updates the history.
|
||||
var workspaceName = '{{.Name}}';
|
||||
</script>
|
||||
{{else}}
|
||||
<section id="content">
|
||||
<h1>Create</h1>
|
||||
<form action="" method="POST">
|
||||
<input class='btn btn-primary btn-lg' type='submit' value='Create a new workspace'>
|
||||
</form>
|
||||
</section>
|
||||
{{end}}
|
||||
{{template "footercommon.html" .}}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,987 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"database/sql"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
htemplate "html/template"
|
||||
"image"
|
||||
_ "image/gif"
|
||||
_ "image/jpeg"
|
||||
"image/png"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
import (
|
||||
"github.com/fiorix/go-web/autogzip"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/golang/glog"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/rcrowley/go-metrics"
|
||||
)
|
||||
|
||||
const (
|
||||
DEFAULT_SAMPLE = `void draw(SkCanvas* canvas) {
|
||||
SkPaint p;
|
||||
p.setColor(SK_ColorRED);
|
||||
p.setAntiAlias(true);
|
||||
p.setStyle(SkPaint::kStroke_Style);
|
||||
p.setStrokeWidth(10);
|
||||
|
||||
canvas->drawLine(20, 20, 100, 100, p);
|
||||
}`
|
||||
// Don't increase above 2^16 w/o altering the db tables to accept something bigger than TEXT.
|
||||
MAX_TRY_SIZE = 64000
|
||||
)
|
||||
|
||||
var (
|
||||
// codeTemplate is the cpp code template the user's code is copied into.
|
||||
codeTemplate *template.Template = nil
|
||||
|
||||
// gypTemplate is the GYP file to build the executable containing the user's code.
|
||||
gypTemplate *template.Template = nil
|
||||
|
||||
// indexTemplate is the main index.html page we serve.
|
||||
indexTemplate *htemplate.Template = nil
|
||||
|
||||
// iframeTemplate is the main index.html page we serve.
|
||||
iframeTemplate *htemplate.Template = nil
|
||||
|
||||
// recentTemplate is a list of recent images.
|
||||
recentTemplate *htemplate.Template = nil
|
||||
|
||||
// workspaceTemplate is the page for workspaces, a series of webtrys.
|
||||
workspaceTemplate *htemplate.Template = nil
|
||||
|
||||
// db is the database, nil if we don't have an SQL database to store data into.
|
||||
db *sql.DB = nil
|
||||
|
||||
// directLink is the regex that matches URLs paths that are direct links.
|
||||
directLink = regexp.MustCompile("^/c/([a-f0-9]+)$")
|
||||
|
||||
// iframeLink is the regex that matches URLs paths that are links to iframes.
|
||||
iframeLink = regexp.MustCompile("^/iframe/([a-f0-9]+)$")
|
||||
|
||||
// imageLink is the regex that matches URLs paths that are direct links to PNGs.
|
||||
imageLink = regexp.MustCompile("^/i/([a-z0-9-_]+.png)$")
|
||||
|
||||
// tryInfoLink is the regex that matches URLs paths that are direct links to data about a single try.
|
||||
tryInfoLink = regexp.MustCompile("^/json/([a-f0-9]+)$")
|
||||
|
||||
// workspaceLink is the regex that matches URLs paths for workspaces.
|
||||
workspaceLink = regexp.MustCompile("^/w/([a-z0-9-]+)$")
|
||||
|
||||
// errorRE is ther regex that matches compiler errors and extracts the line / column information.
|
||||
errorRE = regexp.MustCompile("^.*.cpp:(\\d+):(\\d+):\\s*(.*)")
|
||||
|
||||
// workspaceNameAdj is a list of adjectives for building workspace names.
|
||||
workspaceNameAdj = []string{
|
||||
"autumn", "hidden", "bitter", "misty", "silent", "empty", "dry", "dark",
|
||||
"summer", "icy", "delicate", "quiet", "white", "cool", "spring", "winter",
|
||||
"patient", "twilight", "dawn", "crimson", "wispy", "weathered", "blue",
|
||||
"billowing", "broken", "cold", "damp", "falling", "frosty", "green",
|
||||
"long", "late", "lingering", "bold", "little", "morning", "muddy", "old",
|
||||
"red", "rough", "still", "small", "sparkling", "throbbing", "shy",
|
||||
"wandering", "withered", "wild", "black", "young", "holy", "solitary",
|
||||
"fragrant", "aged", "snowy", "proud", "floral", "restless", "divine",
|
||||
"polished", "ancient", "purple", "lively", "nameless",
|
||||
}
|
||||
|
||||
// workspaceNameNoun is a list of nouns for building workspace names.
|
||||
workspaceNameNoun = []string{
|
||||
"waterfall", "river", "breeze", "moon", "rain", "wind", "sea", "morning",
|
||||
"snow", "lake", "sunset", "pine", "shadow", "leaf", "dawn", "glitter",
|
||||
"forest", "hill", "cloud", "meadow", "sun", "glade", "bird", "brook",
|
||||
"butterfly", "bush", "dew", "dust", "field", "fire", "flower", "firefly",
|
||||
"feather", "grass", "haze", "mountain", "night", "pond", "darkness",
|
||||
"snowflake", "silence", "sound", "sky", "shape", "surf", "thunder",
|
||||
"violet", "water", "wildflower", "wave", "water", "resonance", "sun",
|
||||
"wood", "dream", "cherry", "tree", "fog", "frost", "voice", "paper",
|
||||
"frog", "smoke", "star",
|
||||
}
|
||||
|
||||
gitHash = ""
|
||||
gitInfo = ""
|
||||
|
||||
requestsCounter = metrics.NewRegisteredCounter("requests", metrics.DefaultRegistry)
|
||||
)
|
||||
|
||||
// flags
|
||||
var (
|
||||
useChroot = flag.Bool("use_chroot", false, "Run the compiled code in the schroot jail.")
|
||||
port = flag.String("port", ":8000", "HTTP service address (e.g., ':8000')")
|
||||
)
|
||||
|
||||
// lineNumbers adds #line numbering to the user's code.
|
||||
func LineNumbers(c string) string {
|
||||
lines := strings.Split(c, "\n")
|
||||
ret := []string{}
|
||||
for i, line := range lines {
|
||||
ret = append(ret, fmt.Sprintf("#line %d", i+1))
|
||||
ret = append(ret, line)
|
||||
}
|
||||
return strings.Join(ret, "\n")
|
||||
}
|
||||
|
||||
func Init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
// Change the current working directory to the directory of the executable.
|
||||
cwd, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
||||
if err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
if err := os.Chdir(cwd); err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
|
||||
codeTemplate = template.Must(template.ParseFiles(filepath.Join(cwd, "templates/template.cpp")))
|
||||
gypTemplate = template.Must(template.ParseFiles(filepath.Join(cwd, "templates/template.gyp")))
|
||||
indexTemplate = htemplate.Must(htemplate.ParseFiles(
|
||||
filepath.Join(cwd, "templates/index.html"),
|
||||
filepath.Join(cwd, "templates/titlebar.html"),
|
||||
filepath.Join(cwd, "templates/sidebar.html"),
|
||||
filepath.Join(cwd, "templates/content.html"),
|
||||
filepath.Join(cwd, "templates/headercommon.html"),
|
||||
filepath.Join(cwd, "templates/footercommon.html"),
|
||||
))
|
||||
iframeTemplate = htemplate.Must(htemplate.ParseFiles(
|
||||
filepath.Join(cwd, "templates/iframe.html"),
|
||||
filepath.Join(cwd, "templates/content.html"),
|
||||
filepath.Join(cwd, "templates/headercommon.html"),
|
||||
filepath.Join(cwd, "templates/footercommon.html"),
|
||||
))
|
||||
recentTemplate = htemplate.Must(htemplate.ParseFiles(
|
||||
filepath.Join(cwd, "templates/recent.html"),
|
||||
filepath.Join(cwd, "templates/titlebar.html"),
|
||||
filepath.Join(cwd, "templates/sidebar.html"),
|
||||
filepath.Join(cwd, "templates/headercommon.html"),
|
||||
filepath.Join(cwd, "templates/footercommon.html"),
|
||||
))
|
||||
workspaceTemplate = htemplate.Must(htemplate.ParseFiles(
|
||||
filepath.Join(cwd, "templates/workspace.html"),
|
||||
filepath.Join(cwd, "templates/titlebar.html"),
|
||||
filepath.Join(cwd, "templates/sidebar.html"),
|
||||
filepath.Join(cwd, "templates/content.html"),
|
||||
filepath.Join(cwd, "templates/headercommon.html"),
|
||||
filepath.Join(cwd, "templates/footercommon.html"),
|
||||
))
|
||||
|
||||
// The git command returns output of the format:
|
||||
//
|
||||
// f672cead70404080a991ebfb86c38316a4589b23 2014-04-27 19:21:51 +0000
|
||||
//
|
||||
logOutput, err := doCmd(`git log --format=%H%x20%ai HEAD^..HEAD`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logInfo := strings.Split(logOutput, " ")
|
||||
gitHash = logInfo[0]
|
||||
gitInfo = logInfo[1] + " " + logInfo[2] + " " + logInfo[0][0:6]
|
||||
|
||||
// Connect to MySQL server. First, get the password from the metadata server.
|
||||
// See https://developers.google.com/compute/docs/metadata#custom.
|
||||
req, err := http.NewRequest("GET", "http://metadata/computeMetadata/v1/instance/attributes/password", nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
client := http.Client{}
|
||||
req.Header.Add("X-Google-Metadata-Request", "True")
|
||||
if resp, err := client.Do(req); err == nil {
|
||||
password, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to read password from metadata server: %q\n", err)
|
||||
panic(err)
|
||||
}
|
||||
// The IP address of the database is found here:
|
||||
// https://console.developers.google.com/project/31977622648/sql/instances/webtry/overview
|
||||
// And 3306 is the default port for MySQL.
|
||||
db, err = sql.Open("mysql", fmt.Sprintf("webtry:%s@tcp(173.194.83.52:3306)/webtry?parseTime=true", password))
|
||||
if err != nil {
|
||||
glog.Errorf("ERROR: Failed to open connection to SQL server: %q\n", err)
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
glog.Infof("Failed to find metadata, unable to connect to MySQL server (Expected when running locally): %q\n", err)
|
||||
// Fallback to sqlite for local use.
|
||||
db, err = sql.Open("sqlite3", "./webtry.db")
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to open: %q\n", err)
|
||||
panic(err)
|
||||
}
|
||||
sql := `CREATE TABLE IF NOT EXISTS source_images (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
image MEDIUMBLOB DEFAULT '' NOT NULL, -- formatted as a PNG.
|
||||
width INTEGER DEFAULT 0 NOT NULL,
|
||||
height INTEGER DEFAULT 0 NOT NULL,
|
||||
create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
hidden INTEGER DEFAULT 0 NOT NULL
|
||||
)`
|
||||
_, err = db.Exec(sql)
|
||||
if err != nil {
|
||||
glog.Errorf("Creating source_images table failed: %s", err)
|
||||
}
|
||||
|
||||
sql = `CREATE TABLE IF NOT EXISTS webtry (
|
||||
code TEXT DEFAULT '' NOT NULL,
|
||||
create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
hash CHAR(64) DEFAULT '' NOT NULL,
|
||||
width INTEGER DEFAULT 256 NOT NULL,
|
||||
height INTEGER DEFAULT 256 NOT NULL,
|
||||
source_image_id INTEGER DEFAULT 0 NOT NULL,
|
||||
|
||||
PRIMARY KEY(hash)
|
||||
)`
|
||||
_, err = db.Exec(sql)
|
||||
if err != nil {
|
||||
glog.Errorf("Creating webtry table failed: %s", err)
|
||||
}
|
||||
|
||||
sql = `CREATE TABLE IF NOT EXISTS workspace (
|
||||
name CHAR(64) DEFAULT '' NOT NULL,
|
||||
create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
PRIMARY KEY(name)
|
||||
)`
|
||||
_, err = db.Exec(sql)
|
||||
if err != nil {
|
||||
glog.Errorf("Creating workspace table failed: %s", err)
|
||||
}
|
||||
|
||||
sql = `CREATE TABLE IF NOT EXISTS workspacetry (
|
||||
name CHAR(64) DEFAULT '' NOT NULL,
|
||||
create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
hash CHAR(64) DEFAULT '' NOT NULL,
|
||||
width INTEGER DEFAULT 256 NOT NULL,
|
||||
height INTEGER DEFAULT 256 NOT NULL,
|
||||
hidden INTEGER DEFAULT 0 NOT NULL,
|
||||
source_image_id INTEGER DEFAULT 0 NOT NULL,
|
||||
|
||||
FOREIGN KEY (name) REFERENCES workspace(name)
|
||||
)`
|
||||
_, err = db.Exec(sql)
|
||||
if err != nil {
|
||||
glog.Errorf("Creating workspacetry table failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Ping the database to keep the connection fresh.
|
||||
go func() {
|
||||
c := time.Tick(1 * time.Minute)
|
||||
for _ = range c {
|
||||
if err := db.Ping(); err != nil {
|
||||
glog.Errorf("Database failed to respond: %q\n", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
metrics.RegisterRuntimeMemStats(metrics.DefaultRegistry)
|
||||
go metrics.CaptureRuntimeMemStats(metrics.DefaultRegistry, 1*time.Minute)
|
||||
|
||||
// Start reporting metrics.
|
||||
// TODO(jcgregorio) We need a centrialized config server for storing things
|
||||
// like the IP address of the Graphite monitor.
|
||||
addr, _ := net.ResolveTCPAddr("tcp", "skia-monitoring-b:2003")
|
||||
go metrics.Graphite(metrics.DefaultRegistry, 1*time.Minute, "webtry", addr)
|
||||
|
||||
writeOutAllSourceImages()
|
||||
}
|
||||
|
||||
func writeOutAllSourceImages() {
|
||||
// Pull all the source images from the db and write them out to inout.
|
||||
rows, err := db.Query("SELECT id, image, create_ts FROM source_images ORDER BY create_ts DESC")
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to open connection to SQL server: %q\n", err)
|
||||
panic(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var id int
|
||||
var image []byte
|
||||
var create_ts time.Time
|
||||
if err := rows.Scan(&id, &image, &create_ts); err != nil {
|
||||
glog.Errorf("failed to fetch from database: %q", err)
|
||||
continue
|
||||
}
|
||||
filename := fmt.Sprintf("../../../inout/image-%d.png", id)
|
||||
if _, err := os.Stat(filename); os.IsExist(err) {
|
||||
glog.Infof("Skipping write since file exists: %q", filename)
|
||||
continue
|
||||
}
|
||||
if err := ioutil.WriteFile(filename, image, 0666); err != nil {
|
||||
glog.Errorf("failed to write image file: %q", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titlebar is used in titlebar template expansion.
|
||||
type Titlebar struct {
|
||||
GitHash string
|
||||
GitInfo string
|
||||
}
|
||||
|
||||
// userCode is used in template expansion.
|
||||
type userCode struct {
|
||||
Code string
|
||||
Hash string
|
||||
Width int
|
||||
Height int
|
||||
Source int
|
||||
Titlebar Titlebar
|
||||
}
|
||||
|
||||
// writeTemplate creates a given output file and writes the template
|
||||
// result there.
|
||||
func writeTemplate(filename string, t *template.Template, context interface{}) error {
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
return t.Execute(f, context)
|
||||
}
|
||||
|
||||
// expandToFile expands the template and writes the result to the file.
|
||||
func expandToFile(filename string, code string, t *template.Template) error {
|
||||
return writeTemplate(filename, t, userCode{
|
||||
Code: code,
|
||||
Titlebar: Titlebar{GitHash: gitHash, GitInfo: gitInfo},
|
||||
})
|
||||
}
|
||||
|
||||
// expandCode expands the template into a file and calculates the MD5 hash.
|
||||
// We include the width and height here so that a single hash can capture
|
||||
// both the code and the supplied width/height parameters.
|
||||
func expandCode(code string, source int, width, height int) (string, error) {
|
||||
// in order to support fonts in the chroot jail, we need to make sure
|
||||
// we're using portable typefaces.
|
||||
// TODO(humper): Make this more robust, supporting things like setTypeface
|
||||
|
||||
inputCodeLines := strings.Split(code, "\n")
|
||||
outputCodeLines := []string{
|
||||
"DECLARE_bool(portableFonts);",
|
||||
fmt.Sprintf("// WxH: %d, %d", width, height),
|
||||
}
|
||||
for _, line := range inputCodeLines {
|
||||
outputCodeLines = append(outputCodeLines, line)
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "SkPaint p") {
|
||||
outputCodeLines = append(outputCodeLines, "FLAGS_portableFonts = true;")
|
||||
outputCodeLines = append(outputCodeLines, "sk_tool_utils::set_portable_typeface(&p, \"Helvetica\", SkTypeface::kNormal);")
|
||||
}
|
||||
}
|
||||
|
||||
fontFriendlyCode := strings.Join(outputCodeLines, "\n")
|
||||
|
||||
h := md5.New()
|
||||
h.Write([]byte(fontFriendlyCode))
|
||||
binary.Write(h, binary.LittleEndian, int64(source))
|
||||
hash := fmt.Sprintf("%x", h.Sum(nil))
|
||||
// At this point we are running in skia/experimental/webtry, making cache a
|
||||
// peer directory to skia.
|
||||
// TODO(jcgregorio) Make all relative directories into flags.
|
||||
err := expandToFile(fmt.Sprintf("../../../cache/src/%s.cpp", hash), fontFriendlyCode, codeTemplate)
|
||||
return hash, err
|
||||
}
|
||||
|
||||
// expandGyp produces the GYP file needed to build the code
|
||||
func expandGyp(hash string) error {
|
||||
return writeTemplate(fmt.Sprintf("../../../cache/%s.gyp", hash), gypTemplate, struct{ Hash string }{hash})
|
||||
}
|
||||
|
||||
// response is serialized to JSON as a response to POSTs.
|
||||
type response struct {
|
||||
Message string `json:"message"`
|
||||
CompileErrors []compileError `json:"compileErrors"`
|
||||
RasterImg string `json:"rasterImg"`
|
||||
GPUImg string `json:"gpuImg"`
|
||||
Hash string `json:"hash"`
|
||||
}
|
||||
|
||||
// doCmd executes the given command line string; the command being
|
||||
// run is expected to not care what its current working directory is.
|
||||
// Returns the stdout and stderr.
|
||||
func doCmd(commandLine string) (string, error) {
|
||||
glog.Infof("Command: %q\n", commandLine)
|
||||
programAndArgs := strings.SplitN(commandLine, " ", 2)
|
||||
program := programAndArgs[0]
|
||||
args := []string{}
|
||||
if len(programAndArgs) > 1 {
|
||||
args = strings.Split(programAndArgs[1], " ")
|
||||
}
|
||||
cmd := exec.Command(program, args...)
|
||||
message, err := cmd.CombinedOutput()
|
||||
glog.Infof("StdOut + StdErr: %s\n", string(message))
|
||||
if err != nil {
|
||||
glog.Errorf("Exit status: %s\n", err)
|
||||
return string(message), fmt.Errorf("Failed to run command.")
|
||||
}
|
||||
return string(message), nil
|
||||
}
|
||||
|
||||
// reportError formats an HTTP error response and also logs the detailed error message.
|
||||
func reportError(w http.ResponseWriter, r *http.Request, err error, message string) {
|
||||
glog.Errorf("%s\n%s", message, err)
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
http.Error(w, message, 500)
|
||||
}
|
||||
|
||||
// reportTryError formats an HTTP error response in JSON and also logs the detailed error message.
|
||||
func reportTryError(w http.ResponseWriter, r *http.Request, err error, message, hash string) {
|
||||
m := response{
|
||||
Message: message,
|
||||
Hash: hash,
|
||||
}
|
||||
glog.Errorf("%s\n%s", message, err)
|
||||
resp, err := json.Marshal(m)
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to serialize a response", 500)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
w.Write(resp)
|
||||
}
|
||||
|
||||
func reportCompileError(w http.ResponseWriter, r *http.Request, compileErrors []compileError, hash string) {
|
||||
m := response{
|
||||
CompileErrors: compileErrors,
|
||||
Hash: hash,
|
||||
}
|
||||
|
||||
resp, err := json.Marshal(m)
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to serialize a response", 500)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
w.Write(resp)
|
||||
}
|
||||
|
||||
func writeToDatabase(hash string, code string, workspaceName string, source int, width, height int) {
|
||||
if db == nil {
|
||||
return
|
||||
}
|
||||
if _, err := db.Exec("INSERT INTO webtry (code, hash, width, height, source_image_id) VALUES(?, ?, ?, ?, ?)", code, hash, width, height, source); err != nil {
|
||||
glog.Errorf("Failed to insert code into database: %q\n", err)
|
||||
}
|
||||
if workspaceName != "" {
|
||||
if _, err := db.Exec("INSERT INTO workspacetry (name, hash, width, height, source_image_id) VALUES(?, ?, ?, ?, ?)", workspaceName, hash, width, height, source); err != nil {
|
||||
glog.Errorf("Failed to insert into workspacetry table: %q\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Sources struct {
|
||||
Id int `json:"id"`
|
||||
}
|
||||
|
||||
// sourcesHandler serves up the PNG of a specific try.
|
||||
func sourcesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
glog.Infof("Sources Handler: %q\n", r.URL.Path)
|
||||
if r.Method == "GET" {
|
||||
rows, err := db.Query("SELECT id, create_ts FROM source_images WHERE hidden=0 ORDER BY create_ts DESC")
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Failed to query sources: %s.", err), 500)
|
||||
}
|
||||
defer rows.Close()
|
||||
sources := make([]Sources, 0, 0)
|
||||
for rows.Next() {
|
||||
var id int
|
||||
var create_ts time.Time
|
||||
if err := rows.Scan(&id, &create_ts); err != nil {
|
||||
glog.Errorf("failed to fetch from database: %q", err)
|
||||
continue
|
||||
}
|
||||
sources = append(sources, Sources{Id: id})
|
||||
}
|
||||
|
||||
resp, err := json.Marshal(sources)
|
||||
if err != nil {
|
||||
reportError(w, r, err, "Failed to serialize a response.")
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(resp)
|
||||
|
||||
} else if r.Method == "POST" {
|
||||
if err := r.ParseMultipartForm(1000000); err != nil {
|
||||
http.Error(w, fmt.Sprintf("Failed to load image: %s.", err), 500)
|
||||
return
|
||||
}
|
||||
if _, ok := r.MultipartForm.File["upload"]; !ok {
|
||||
http.Error(w, "Invalid upload.", 500)
|
||||
return
|
||||
}
|
||||
if len(r.MultipartForm.File["upload"]) != 1 {
|
||||
http.Error(w, "Wrong number of uploads.", 500)
|
||||
return
|
||||
}
|
||||
f, err := r.MultipartForm.File["upload"][0].Open()
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Failed to load image: %s.", err), 500)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
m, _, err := image.Decode(f)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Failed to decode image: %s.", err), 500)
|
||||
return
|
||||
}
|
||||
var b bytes.Buffer
|
||||
png.Encode(&b, m)
|
||||
bounds := m.Bounds()
|
||||
width := bounds.Max.Y - bounds.Min.Y
|
||||
height := bounds.Max.X - bounds.Min.X
|
||||
if _, err := db.Exec("INSERT INTO source_images (image, width, height) VALUES(?, ?, ?)", b.Bytes(), width, height); err != nil {
|
||||
glog.Errorf("Failed to insert sources into database: %q\n", err)
|
||||
http.Error(w, fmt.Sprintf("Failed to store image: %s.", err), 500)
|
||||
return
|
||||
}
|
||||
go writeOutAllSourceImages()
|
||||
|
||||
// Now redirect back to where we came from.
|
||||
http.Redirect(w, r, r.Referer(), 302)
|
||||
} else {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// imageHandler serves up the PNG of a specific try.
|
||||
func imageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
glog.Infof("Image Handler: %q\n", r.URL.Path)
|
||||
if r.Method != "GET" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
match := imageLink.FindStringSubmatch(r.URL.Path)
|
||||
if len(match) != 2 {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
filename := match[1]
|
||||
w.Header().Set("Content-Type", "image/png")
|
||||
http.ServeFile(w, r, fmt.Sprintf("../../../inout/%s", filename))
|
||||
}
|
||||
|
||||
type Try struct {
|
||||
Hash string `json:"hash"`
|
||||
Source int
|
||||
CreateTS string `json:"create_ts"`
|
||||
}
|
||||
|
||||
type Recent struct {
|
||||
Tries []Try
|
||||
Titlebar Titlebar
|
||||
}
|
||||
|
||||
// recentHandler shows the last 20 tries.
|
||||
func recentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
glog.Infof("Recent Handler: %q\n", r.URL.Path)
|
||||
|
||||
rows, err := db.Query("SELECT create_ts, hash FROM webtry ORDER BY create_ts DESC LIMIT 20")
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
recent := []Try{}
|
||||
for rows.Next() {
|
||||
var hash string
|
||||
var create_ts time.Time
|
||||
if err := rows.Scan(&create_ts, &hash); err != nil {
|
||||
glog.Errorf("failed to fetch from database: %q", err)
|
||||
continue
|
||||
}
|
||||
recent = append(recent, Try{Hash: hash, CreateTS: create_ts.Format("2006-02-01")})
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
if err := recentTemplate.Execute(w, Recent{Tries: recent, Titlebar: Titlebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil {
|
||||
glog.Errorf("Failed to expand template: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
type Workspace struct {
|
||||
Name string
|
||||
Code string
|
||||
Hash string
|
||||
Width int
|
||||
Height int
|
||||
Source int
|
||||
Tries []Try
|
||||
Titlebar Titlebar
|
||||
}
|
||||
|
||||
// newWorkspace generates a new random workspace name and stores it in the database.
|
||||
func newWorkspace() (string, error) {
|
||||
for i := 0; i < 10; i++ {
|
||||
adj := workspaceNameAdj[rand.Intn(len(workspaceNameAdj))]
|
||||
noun := workspaceNameNoun[rand.Intn(len(workspaceNameNoun))]
|
||||
suffix := rand.Intn(1000)
|
||||
name := fmt.Sprintf("%s-%s-%d", adj, noun, suffix)
|
||||
if _, err := db.Exec("INSERT INTO workspace (name) VALUES(?)", name); err == nil {
|
||||
return name, nil
|
||||
} else {
|
||||
glog.Errorf("Failed to insert workspace into database: %q\n", err)
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("Failed to create a new workspace")
|
||||
}
|
||||
|
||||
// getCode returns the code for a given hash, or the empty string if not found.
|
||||
func getCode(hash string) (string, int, int, int, error) {
|
||||
code := ""
|
||||
width := 0
|
||||
height := 0
|
||||
source := 0
|
||||
if err := db.QueryRow("SELECT code, width, height, source_image_id FROM webtry WHERE hash=?", hash).Scan(&code, &width, &height, &source); err != nil {
|
||||
glog.Errorf("Code for hash is missing: %q\n", err)
|
||||
return code, width, height, source, err
|
||||
}
|
||||
return code, width, height, source, nil
|
||||
}
|
||||
|
||||
func workspaceHandler(w http.ResponseWriter, r *http.Request) {
|
||||
glog.Infof("Workspace Handler: %q\n", r.URL.Path)
|
||||
if r.Method == "GET" {
|
||||
tries := []Try{}
|
||||
match := workspaceLink.FindStringSubmatch(r.URL.Path)
|
||||
name := ""
|
||||
if len(match) == 2 {
|
||||
name = match[1]
|
||||
rows, err := db.Query("SELECT create_ts, hash, source_image_id FROM workspacetry WHERE name=? ORDER BY create_ts", name)
|
||||
if err != nil {
|
||||
reportError(w, r, err, "Failed to select.")
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var hash string
|
||||
var create_ts time.Time
|
||||
var source int
|
||||
if err := rows.Scan(&create_ts, &hash, &source); err != nil {
|
||||
glog.Errorf("failed to fetch from database: %q", err)
|
||||
continue
|
||||
}
|
||||
tries = append(tries, Try{Hash: hash, Source: source, CreateTS: create_ts.Format("2006-02-01")})
|
||||
}
|
||||
}
|
||||
var code string
|
||||
var hash string
|
||||
var width int
|
||||
var height int
|
||||
source := 0
|
||||
if len(tries) == 0 {
|
||||
code = DEFAULT_SAMPLE
|
||||
width = 256
|
||||
height = 256
|
||||
} else {
|
||||
hash = tries[len(tries)-1].Hash
|
||||
code, width, height, source, _ = getCode(hash)
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
if err := workspaceTemplate.Execute(w, Workspace{Tries: tries, Code: code, Name: name, Hash: hash, Width: width, Height: height, Source: source, Titlebar: Titlebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil {
|
||||
glog.Errorf("Failed to expand template: %q\n", err)
|
||||
}
|
||||
} else if r.Method == "POST" {
|
||||
name, err := newWorkspace()
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to create a new workspace.", 500)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/w/"+name, 302)
|
||||
}
|
||||
}
|
||||
|
||||
// hasPreProcessor returns true if any line in the code begins with a # char.
|
||||
func hasPreProcessor(code string) bool {
|
||||
lines := strings.Split(code, "\n")
|
||||
for _, s := range lines {
|
||||
if strings.HasPrefix(strings.TrimSpace(s), "#") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type TryRequest struct {
|
||||
Code string `json:"code"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
GPU bool `json:"gpu"`
|
||||
Raster bool `json:"raster"`
|
||||
PDF bool `json:"pdf"`
|
||||
Name string `json:"name"` // Optional name of the workspace the code is in.
|
||||
Source int `json:"source"` // ID of the source image, 0 if none.
|
||||
}
|
||||
|
||||
// iframeHandler handles the GET and POST of the main page.
|
||||
func iframeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
glog.Infof("IFrame Handler: %q\n", r.URL.Path)
|
||||
if r.Method != "GET" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
match := iframeLink.FindStringSubmatch(r.URL.Path)
|
||||
if len(match) != 2 {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
hash := match[1]
|
||||
if db == nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
var code string
|
||||
code, width, height, source, err := getCode(hash)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
// Expand the template.
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
if err := iframeTemplate.Execute(w, userCode{Code: code, Width: width, Height: height, Hash: hash, Source: source}); err != nil {
|
||||
glog.Errorf("Failed to expand template: %q\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
type TryInfo struct {
|
||||
Hash string `json:"hash"`
|
||||
Code string `json:"code"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
Source int `json:"source"`
|
||||
}
|
||||
|
||||
// tryInfoHandler returns information about a specific try.
|
||||
func tryInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
glog.Infof("Try Info Handler: %q\n", r.URL.Path)
|
||||
if r.Method != "GET" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
match := tryInfoLink.FindStringSubmatch(r.URL.Path)
|
||||
if len(match) != 2 {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
hash := match[1]
|
||||
code, width, height, source, err := getCode(hash)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
m := TryInfo{
|
||||
Hash: hash,
|
||||
Code: code,
|
||||
Width: width,
|
||||
Height: height,
|
||||
Source: source,
|
||||
}
|
||||
resp, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
reportError(w, r, err, "Failed to serialize a response.")
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(resp)
|
||||
}
|
||||
|
||||
func cleanCompileOutput(s, hash string) string {
|
||||
old := "../../../cache/src/" + hash + ".cpp:"
|
||||
glog.Infof("replacing %q\n", old)
|
||||
return strings.Replace(s, old, "usercode.cpp:", -1)
|
||||
}
|
||||
|
||||
type compileError struct {
|
||||
Line int `json:"line"`
|
||||
Column int `json:"column"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// mainHandler handles the GET and POST of the main page.
|
||||
func mainHandler(w http.ResponseWriter, r *http.Request) {
|
||||
glog.Infof("Main Handler: %q\n", r.URL.Path)
|
||||
requestsCounter.Inc(1)
|
||||
if r.Method == "GET" {
|
||||
code := DEFAULT_SAMPLE
|
||||
source := 0
|
||||
width := 256
|
||||
height := 256
|
||||
match := directLink.FindStringSubmatch(r.URL.Path)
|
||||
var hash string
|
||||
if len(match) == 2 && r.URL.Path != "/" {
|
||||
hash = match[1]
|
||||
if db == nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
// Update 'code' with the code found in the database.
|
||||
if err := db.QueryRow("SELECT code, width, height, source_image_id FROM webtry WHERE hash=?", hash).Scan(&code, &width, &height, &source); err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
// Expand the template.
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
if err := indexTemplate.Execute(w, userCode{Code: code, Hash: hash, Source: source, Width: width, Height: height, Titlebar: Titlebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil {
|
||||
glog.Errorf("Failed to expand template: %q\n", err)
|
||||
}
|
||||
} else if r.Method == "POST" {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
buf := bytes.NewBuffer(make([]byte, 0, MAX_TRY_SIZE))
|
||||
n, err := buf.ReadFrom(r.Body)
|
||||
if err != nil {
|
||||
reportTryError(w, r, err, "Failed to read a request body.", "")
|
||||
return
|
||||
}
|
||||
if n == MAX_TRY_SIZE {
|
||||
err := fmt.Errorf("Code length equal to, or exceeded, %d", MAX_TRY_SIZE)
|
||||
reportTryError(w, r, err, "Code too large.", "")
|
||||
return
|
||||
}
|
||||
request := TryRequest{}
|
||||
if err := json.Unmarshal(buf.Bytes(), &request); err != nil {
|
||||
reportTryError(w, r, err, "Coulnd't decode JSON.", "")
|
||||
return
|
||||
}
|
||||
if !(request.GPU || request.Raster || request.PDF) {
|
||||
reportTryError(w, r, nil, "No run configuration supplied...", "")
|
||||
return
|
||||
}
|
||||
if hasPreProcessor(request.Code) {
|
||||
err := fmt.Errorf("Found preprocessor macro in code.")
|
||||
reportTryError(w, r, err, "Preprocessor macros aren't allowed.", "")
|
||||
return
|
||||
}
|
||||
hash, err := expandCode(LineNumbers(request.Code), request.Source, request.Width, request.Height)
|
||||
if err != nil {
|
||||
reportTryError(w, r, err, "Failed to write the code to compile.", hash)
|
||||
return
|
||||
}
|
||||
writeToDatabase(hash, request.Code, request.Name, request.Source, request.Width, request.Height)
|
||||
err = expandGyp(hash)
|
||||
if err != nil {
|
||||
reportTryError(w, r, err, "Failed to write the gyp file.", hash)
|
||||
return
|
||||
}
|
||||
cmd := fmt.Sprintf("scripts/fiddle_wrapper %s --width %d --height %d", hash, request.Width, request.Height)
|
||||
if request.Raster {
|
||||
cmd += " --raster"
|
||||
}
|
||||
if request.GPU {
|
||||
cmd += " --gpu"
|
||||
}
|
||||
if request.PDF {
|
||||
cmd += " --pdf"
|
||||
}
|
||||
if *useChroot {
|
||||
cmd = "schroot -c webtry --directory=/ -- /skia_build/skia/experimental/webtry/" + cmd
|
||||
}
|
||||
if request.Source > 0 {
|
||||
cmd += fmt.Sprintf(" --source image-%d.png", request.Source)
|
||||
}
|
||||
|
||||
message, err := doCmd(cmd)
|
||||
|
||||
outputLines := strings.Split(message, "\n")
|
||||
errorLines := []compileError{}
|
||||
for _, line := range outputLines {
|
||||
match := errorRE.FindStringSubmatch(line)
|
||||
if len(match) > 0 {
|
||||
lineNumber, parseError := strconv.Atoi(match[1])
|
||||
if parseError != nil {
|
||||
glog.Errorf("ERROR: Couldn't parse line number from %s\n", match[1])
|
||||
continue
|
||||
}
|
||||
columnNumber, parseError := strconv.Atoi(match[2])
|
||||
if parseError != nil {
|
||||
glog.Errorf("ERROR: Couldn't parse column number from %s\n", match[2])
|
||||
continue
|
||||
}
|
||||
errorLines = append(errorLines,
|
||||
compileError{
|
||||
Line: lineNumber,
|
||||
Column: columnNumber,
|
||||
Error: match[3],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if len(errorLines) > 0 {
|
||||
reportCompileError(w, r, errorLines, hash)
|
||||
} else {
|
||||
reportTryError(w, r, err, "Failed to run the code:\n"+message, hash)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
m := response{
|
||||
Hash: hash,
|
||||
}
|
||||
|
||||
if request.Raster {
|
||||
png, err := ioutil.ReadFile("../../../inout/" + hash + "_raster.png")
|
||||
if err != nil {
|
||||
reportTryError(w, r, err, "Failed to open the raster-generated PNG.", hash)
|
||||
return
|
||||
}
|
||||
|
||||
m.RasterImg = base64.StdEncoding.EncodeToString([]byte(png))
|
||||
}
|
||||
|
||||
if request.GPU {
|
||||
png, err := ioutil.ReadFile("../../../inout/" + hash + "_gpu.png")
|
||||
if err != nil {
|
||||
reportTryError(w, r, err, "Failed to open the GPU-generated PNG.", hash)
|
||||
return
|
||||
}
|
||||
|
||||
m.GPUImg = base64.StdEncoding.EncodeToString([]byte(png))
|
||||
}
|
||||
|
||||
resp, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
reportTryError(w, r, err, "Failed to serialize a response.", hash)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(resp)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
Init()
|
||||
http.HandleFunc("/i/", autogzip.HandleFunc(imageHandler))
|
||||
http.HandleFunc("/w/", autogzip.HandleFunc(workspaceHandler))
|
||||
http.HandleFunc("/recent/", autogzip.HandleFunc(recentHandler))
|
||||
http.HandleFunc("/iframe/", autogzip.HandleFunc(iframeHandler))
|
||||
http.HandleFunc("/json/", autogzip.HandleFunc(tryInfoHandler))
|
||||
http.HandleFunc("/sources/", autogzip.HandleFunc(sourcesHandler))
|
||||
|
||||
// Resources are served directly
|
||||
// TODO add support for caching/etags/gzip
|
||||
http.Handle("/res/", autogzip.Handle(http.FileServer(http.Dir("./"))))
|
||||
|
||||
// TODO Break out /c/ as it's own handler.
|
||||
http.HandleFunc("/", autogzip.HandleFunc(mainHandler))
|
||||
glog.Fatal(http.ListenAndServe(*port, nil))
|
||||
}
|
Loading…
Reference in New Issue
Block a user