mirror of
https://github.com/spacedeck/spacedeck-open.git
synced 2025-12-15 09:27:31 +01:00
Merge pull request #169 from bckmnn/dev/puppeteer
replace phantom js with puppeteer
This commit is contained in:
14
Dockerfile
14
Dockerfile
@@ -21,6 +21,20 @@ RUN cd audiowaveform/build/ && cmake -D ENABLE_TESTS=0 -D BUILD_STATIC=1 ..
|
||||
RUN cd audiowaveform/build/ && make
|
||||
RUN cd audiowaveform/build/ && make install
|
||||
|
||||
# install chromium
|
||||
RUN apk add --no-cache \
|
||||
chromium \
|
||||
nss \
|
||||
freetype \
|
||||
freetype-dev \
|
||||
harfbuzz \
|
||||
ca-certificates \
|
||||
ttf-freefont
|
||||
|
||||
# Tell Puppeteer to skip installing Chrome. We'll be using the installed package.
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
|
||||
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
|
||||
|
||||
# install other requirements
|
||||
|
||||
RUN apk add graphicsmagick ffmpeg ffmpeg-dev ghostscript
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"redis_mock": true,
|
||||
"redis_host": "localhost",
|
||||
|
||||
"phantom_api_secret": "very_secret_phantom_password",
|
||||
"export_api_secret": "very_secret_export_password",
|
||||
|
||||
"mail_provider": "smtp",
|
||||
"mail_smtp_host": "your.smtp.host",
|
||||
|
||||
58
helpers/exporter.js
Normal file
58
helpers/exporter.js
Normal file
@@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
|
||||
const db = require('../models/db');
|
||||
const config = require('config');
|
||||
const puppeteer = require('puppeteer');
|
||||
const os = require('os');
|
||||
|
||||
module.exports = {
|
||||
// type = "pdf" or "png"
|
||||
takeScreenshot: function(space,type,on_success,on_error) {
|
||||
var spaceId = space._id;
|
||||
var space_url = config.get("endpoint")+"/api/spaces/"+spaceId+"/html";
|
||||
|
||||
var export_path = os.tmpdir()+"/"+spaceId+"."+type;
|
||||
|
||||
var timeout = 5000;
|
||||
if (type=="pdf") timeout = 30000;
|
||||
|
||||
space_url += "?api_token="+config.get("export_api_secret");
|
||||
|
||||
console.log("[space-screenshot] url: "+space_url);
|
||||
console.log("[space-screenshot] export_path: "+export_path);
|
||||
|
||||
(async () => {
|
||||
let browser;
|
||||
let page;
|
||||
try {
|
||||
browser = await puppeteer.launch(
|
||||
{
|
||||
headless: true,
|
||||
args: ['--disable-dev-shm-usage', '--no-sandbox']
|
||||
}
|
||||
);
|
||||
page = await browser.newPage();
|
||||
|
||||
page.setDefaultTimeout(timeout);
|
||||
await page.setJavaScriptEnabled(false);
|
||||
await page.goto(space_url, {waitUntil: 'networkidle2'});
|
||||
await page.emulateMediaType('screen');
|
||||
|
||||
if (type=="pdf") {
|
||||
let margin = 2;
|
||||
await page.pdf({path: export_path, printBackground: true, width: space.width+margin+'px', height: space.height+margin+'px' });
|
||||
}else{
|
||||
await page.screenshot({path: export_path, printBackground: true});
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
on_success(export_path);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error("[space-screenshot] puppeteer abnormal exit for url "+space_url);
|
||||
on_error();
|
||||
}
|
||||
|
||||
})();
|
||||
}
|
||||
};
|
||||
@@ -1,70 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const db = require('../models/db');
|
||||
const config = require('config');
|
||||
const phantom = require('node-phantom-simple');
|
||||
const os = require('os');
|
||||
|
||||
module.exports = {
|
||||
// type = "pdf" or "png"
|
||||
takeScreenshot: function(space,type,on_success,on_error) {
|
||||
var spaceId = space._id;
|
||||
var space_url = config.get("endpoint")+"/api/spaces/"+spaceId+"/html";
|
||||
|
||||
var export_path = os.tmpdir()+"/"+spaceId+"."+type;
|
||||
|
||||
var timeout = 5000;
|
||||
if (type=="pdf") timeout = 30000;
|
||||
|
||||
space_url += "?api_token="+config.get("phantom_api_secret");
|
||||
|
||||
console.log("[space-screenshot] url: "+space_url);
|
||||
console.log("[space-screenshot] export_path: "+export_path);
|
||||
|
||||
var on_success_called = false;
|
||||
|
||||
var on_exit = function(exit_code) {
|
||||
if (exit_code>0) {
|
||||
console.error("phantom abnormal exit for url "+space_url);
|
||||
if (!on_success_called && on_error) {
|
||||
on_error();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
phantom.create({ path: require('phantomjs-prebuilt').path }, function (err, browser) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
} else {
|
||||
return browser.createPage(function (err, page) {
|
||||
console.log("page created, opening ",space_url);
|
||||
|
||||
if (type=="pdf") {
|
||||
var psz = {
|
||||
width: space.width+"px",
|
||||
height: space.height+"px"
|
||||
};
|
||||
page.set('paperSize', psz);
|
||||
}
|
||||
|
||||
page.set('settings.resourceTimeout',timeout);
|
||||
page.set('settings.javascriptEnabled',false);
|
||||
|
||||
return page.open(space_url, function (err,status) {
|
||||
page.render(export_path, function() {
|
||||
on_success_called = true;
|
||||
if (on_success) {
|
||||
on_success(export_path);
|
||||
}
|
||||
page.close();
|
||||
browser.exit();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}, {
|
||||
onExit: on_exit
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -320,5 +320,6 @@
|
||||
"follow_present": "Folgen",
|
||||
"mute_present": "Entfolgen",
|
||||
"follow_present_help": "Wenn jemand den Space präsentiert, folgen die anderen Mitglieder automatisch der Präsentation. Mit diesem Knopf lässt sich das an- oder ausschalten.",
|
||||
"media": "Media"
|
||||
}
|
||||
"media": "Media",
|
||||
"tool_edit_text": "Text bearbeiten"
|
||||
}
|
||||
@@ -86,7 +86,7 @@ module.exports = (req, res, next) => {
|
||||
// space is private
|
||||
|
||||
// special permission for screenshot/pdf export from backend
|
||||
if (req.query['api_token'] && req.query['api_token'] == config.get('phantom_api_secret')) {
|
||||
if (req.query['api_token'] && req.query['api_token'] == config.get('export_api_secret')) {
|
||||
finalizeReq(space, "viewer");
|
||||
return;
|
||||
}
|
||||
|
||||
7466
package-lock.json
generated
Normal file
7466
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -30,10 +30,8 @@
|
||||
"mock-aws-s3": "^2.6.0",
|
||||
"moment": "^2.19.3",
|
||||
"morgan": "^1.9.1",
|
||||
"node-phantom-simple": "2.2.4",
|
||||
"node-server-screenshot": "^0.2.1",
|
||||
"nodemailer": "^4.6.7",
|
||||
"phantomjs-prebuilt": "^2.1.16",
|
||||
"puppeteer": "8.0.0",
|
||||
"read-chunk": "^2.1.0",
|
||||
"request": "^2.88.0",
|
||||
"sanitize-html": "^1.11.1",
|
||||
|
||||
@@ -23,6 +23,9 @@ function vec2_angle(v) {
|
||||
function render_vector_drawing(a, padding) {
|
||||
var shape = a.shape || "";
|
||||
var path = [];
|
||||
if(typeof a.control_points == 'string'){
|
||||
a.control_points = JSON.parse(a.control_points);
|
||||
}
|
||||
var p = a.control_points[0];
|
||||
|
||||
if (!p) return "";
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5,7 +5,7 @@ const db = require('../../models/db');
|
||||
var mailer = require('../../helpers/mailer');
|
||||
var uploader = require('../../helpers/uploader');
|
||||
var space_render = require('../../helpers/space-render');
|
||||
var phantom = require('../../helpers/phantom');
|
||||
var exporter = require('../../helpers/exporter');
|
||||
|
||||
var async = require('async');
|
||||
var moment = require('moment');
|
||||
@@ -51,7 +51,7 @@ router.get('/png', function(req, res, next) {
|
||||
if (!req.space.thumbnail_updated_at || req.space.thumbnail_updated_at < req.space.updated_at || !req.space.thumbnail_url) {
|
||||
db.Space.update({ thumbnail_updated_at: triggered }, {where : {"_id": req.space._id }});
|
||||
|
||||
phantom.takeScreenshot(req.space, "png", function(local_path) {
|
||||
exporter.takeScreenshot(req.space, "png", function(local_path) {
|
||||
var localResizedFilePath = local_path + ".thumb.jpg";
|
||||
gm(local_path).resize(640, 480).quality(70.0).autoOrient().write(localResizedFilePath, function(err) {
|
||||
|
||||
@@ -109,7 +109,7 @@ function make_export_filename(space, extension) {
|
||||
router.get('/pdf', function(req, res, next) {
|
||||
var s3_filename = make_export_filename(req.space, "pdf");
|
||||
|
||||
phantom.takeScreenshot(req.space, "pdf", function(local_path) {
|
||||
exporter.takeScreenshot(req.space, "pdf", function(local_path) {
|
||||
uploader.uploadFile(s3_filename, "application/pdf", local_path, function(err, url) {
|
||||
res.status(201).json({
|
||||
url: url
|
||||
|
||||
@@ -9,7 +9,7 @@ var redis = require('../../helpers/redis');
|
||||
var mailer = require('../../helpers/mailer');
|
||||
var uploader = require('../../helpers/uploader');
|
||||
var space_render = require('../../helpers/space-render');
|
||||
var phantom = require('../../helpers/phantom');
|
||||
var exporter = require('../../helpers/exporter');
|
||||
|
||||
var async = require('async');
|
||||
var fs = require('fs');
|
||||
|
||||
@@ -10,7 +10,7 @@ var redis = require('../../helpers/redis');
|
||||
var mailer = require('../../helpers/mailer');
|
||||
var uploader = require('../../helpers/uploader');
|
||||
var space_render = require('../../helpers/space-render');
|
||||
var phantom = require('../../helpers/phantom');
|
||||
var exporter = require('../../helpers/exporter');
|
||||
var payloadConverter = require('../../helpers/artifact_converter');
|
||||
|
||||
var slug = require('slug');
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
var config = require('config');
|
||||
require('../../models/db');
|
||||
|
||||
var fs = require('fs');
|
||||
var phantom = require('node-phantom-simple');
|
||||
var md5 = require('md5');
|
||||
|
||||
var express = require('express');
|
||||
@@ -19,40 +19,39 @@ function website_to_png(url,on_success,on_error) {
|
||||
console.log("[webgrabber] url: "+url);
|
||||
console.log("[webgrabber] export_path: "+export_path);
|
||||
|
||||
var on_success_called = false;
|
||||
|
||||
var on_exit = function(exit_code) {
|
||||
if (exit_code>0) {
|
||||
console.log("[phantom-webgrabber] abnormal exit for url "+url);
|
||||
if (!on_success_called && on_error) {
|
||||
on_error();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fs.stat(export_path, function(err, stat) {
|
||||
if (!err) {
|
||||
// file exists
|
||||
console.log("[webgrabber] serving cached snapshot of url: "+url);
|
||||
on_success(export_path);
|
||||
} else {
|
||||
phantom.create({ path: require('phantomjs-prebuilt').path }, function (err, browser) {
|
||||
return browser.createPage(function (err, page) {
|
||||
page.set('settings.resourceTimeout',timeout);
|
||||
page.set('settings.javascriptEnabled',false);
|
||||
|
||||
return page.open(url, function(err, status) {
|
||||
console.log("[webgrabber] status: "+status);
|
||||
page.render(export_path, function() {
|
||||
on_success_called = true;
|
||||
on_success(export_path);
|
||||
browser.exit();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, {
|
||||
onExit: on_exit
|
||||
});
|
||||
(async () => {
|
||||
let browser;
|
||||
let page;
|
||||
try {
|
||||
browser = await puppeteer.launch(
|
||||
{
|
||||
headless: true,
|
||||
args: ['--disable-dev-shm-usage', '--no-sandbox']
|
||||
}
|
||||
);
|
||||
page = await browser.newPage();
|
||||
|
||||
page.setDefaultTimeout(timeout);
|
||||
await page.setJavaScriptEnabled(false);
|
||||
await page.goto(url, {waitUntil: 'networkidle2'});
|
||||
await page.emulateMedia('screen');
|
||||
await page.screenshot({path: export_path, printBackground: true});
|
||||
|
||||
await browser.close();
|
||||
on_success(export_path);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.log("[webgrabber] puppeteer abnormal exit for url "+url);
|
||||
on_error();
|
||||
}
|
||||
|
||||
})();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,12 +3,17 @@
|
||||
@import "unicode";
|
||||
|
||||
@-webkit-keyframes appear {
|
||||
0% { opacity: 0;}
|
||||
30% { opacity: 0;}
|
||||
100% { opacity: 1; }
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
30% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.avatar {
|
||||
background-color: $blue;
|
||||
font-family: $main-font;
|
||||
@@ -26,7 +31,9 @@
|
||||
#user-root {
|
||||
margin-left: 5px !important;
|
||||
padding: 0px !important;
|
||||
.btn {margin-right: 10px; }
|
||||
.btn {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
#sidebar.folder-sidebar {
|
||||
@@ -70,7 +77,9 @@
|
||||
li {
|
||||
display: inline-block;
|
||||
line-height: 44px;
|
||||
&.active span {color: $light; }
|
||||
&.active span {
|
||||
color: $light;
|
||||
}
|
||||
span {
|
||||
color: $medium;
|
||||
display: inline-block;
|
||||
@@ -82,8 +91,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#folder {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
@@ -137,7 +144,7 @@
|
||||
z-index: initial;
|
||||
}
|
||||
|
||||
.folder .icon {
|
||||
.folder .icon {
|
||||
color: $yellow;
|
||||
opacity: 1;
|
||||
}
|
||||
@@ -150,7 +157,7 @@
|
||||
width: 100%;
|
||||
}
|
||||
> .icon {
|
||||
margin-left: -15px
|
||||
margin-left: -15px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,30 +183,30 @@
|
||||
// margin-top: -18px;
|
||||
margin-right: -60px;
|
||||
// margin-bottom: -18px;
|
||||
@include transition( all 0.125s ease-in-out);
|
||||
@include transition(all 0.125s ease-in-out);
|
||||
.icon {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
line-height: 60px;
|
||||
font-size: 13px;
|
||||
position: absolute;
|
||||
@include scale(0,0);
|
||||
@include transition( all 0.125s ease-in-out);
|
||||
@include scale(0, 0);
|
||||
@include transition(all 0.125s ease-in-out);
|
||||
@include opacity(0.25);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
margin-right: -12px;
|
||||
.icon {
|
||||
@include scale(1,1);
|
||||
@include scale(1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#folder-header {
|
||||
background-color: rgba(41,41,41,0.95);
|
||||
background-color: rgba(245,245,245,0.95);
|
||||
background-color: rgba(41, 41, 41, 0.95);
|
||||
background-color: rgba(245, 245, 245, 0.95);
|
||||
}
|
||||
|
||||
#folder-wrapper {
|
||||
@@ -212,15 +219,22 @@
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
|
||||
#folder-grid .item {
|
||||
float: left;
|
||||
width: 100%;
|
||||
|
||||
@media screen and (min-width: 640px) {width: 50%; }
|
||||
@media screen and (min-width: 800px) {width: 33.333333%; }
|
||||
@media screen and (min-width: 1000px) {width: 25%; }
|
||||
@media screen and (min-width: 1200px) {width: 20%; }
|
||||
@media screen and (min-width: 640px) {
|
||||
width: 50%;
|
||||
}
|
||||
@media screen and (min-width: 800px) {
|
||||
width: 33.333333%;
|
||||
}
|
||||
@media screen and (min-width: 1000px) {
|
||||
width: 25%;
|
||||
}
|
||||
@media screen and (min-width: 1200px) {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
.compact-hidden {
|
||||
@@ -256,8 +270,8 @@
|
||||
.item {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
padding-right: $folder-gutter*2;
|
||||
padding-bottom: $folder-gutter*2;
|
||||
padding-right: $folder-gutter * 2;
|
||||
padding-bottom: $folder-gutter * 2;
|
||||
margin-bottom: $folder-gutter;
|
||||
|
||||
position: relative;
|
||||
@@ -265,36 +279,38 @@
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
.folder-drop {display:none; }
|
||||
.folder-drop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.appear > a,
|
||||
&.creating > a {
|
||||
opacity: 0;
|
||||
-webkit-animation: appear 0.25s ease-out 0.05s;
|
||||
-moz-animation: appear 0.25s ease-out 0.05s;
|
||||
-ms-animation: appear 0.25s ease-out 0.05s;
|
||||
-o-animation: appear 0.25s ease-out 0.05s;
|
||||
animation: appear 0.25s ease-out 0.05s;
|
||||
-moz-animation: appear 0.25s ease-out 0.05s;
|
||||
-ms-animation: appear 0.25s ease-out 0.05s;
|
||||
-o-animation: appear 0.25s ease-out 0.05s;
|
||||
animation: appear 0.25s ease-out 0.05s;
|
||||
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
-moz-animation-fill-mode: forwards;
|
||||
-ms-animation-fill-mode: forwards;
|
||||
-o-animation-fill-mode: forwards;
|
||||
animation-fill-mode: forwards;
|
||||
-moz-animation-fill-mode: forwards;
|
||||
-ms-animation-fill-mode: forwards;
|
||||
-o-animation-fill-mode: forwards;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
&.deleting > a {
|
||||
-webkit-animation: disappear 0.25s ease-out 0.05s;
|
||||
-moz-animation: disappear 0.25s ease-out 0.05s;
|
||||
-ms-animation: disappear 0.25s ease-out 0.05s;
|
||||
-o-animation: disappear 0.25s ease-out 0.05s;
|
||||
animation: disappear 0.25s ease-out 0.05s;
|
||||
-moz-animation: disappear 0.25s ease-out 0.05s;
|
||||
-ms-animation: disappear 0.25s ease-out 0.05s;
|
||||
-o-animation: disappear 0.25s ease-out 0.05s;
|
||||
animation: disappear 0.25s ease-out 0.05s;
|
||||
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
-moz-animation-fill-mode: forwards;
|
||||
-ms-animation-fill-mode: forwards;
|
||||
-o-animation-fill-mode: forwards;
|
||||
animation-fill-mode: forwards;
|
||||
-moz-animation-fill-mode: forwards;
|
||||
-ms-animation-fill-mode: forwards;
|
||||
-o-animation-fill-mode: forwards;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
&.tag-important > a {
|
||||
@@ -308,7 +324,7 @@
|
||||
|
||||
&.dropping {
|
||||
.folder-drop {
|
||||
display:block;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,7 +365,13 @@
|
||||
background-color: $darker;
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
-webkit-mask-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,0)), to(rgba(0,0,0,0.1)));
|
||||
-webkit-mask-image: -webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
left bottom,
|
||||
from(rgba(0, 0, 0, 0)),
|
||||
to(rgba(0, 0, 0, 0.1))
|
||||
);
|
||||
background-color: black;
|
||||
pointer-events: none;
|
||||
}
|
||||
@@ -360,7 +382,7 @@
|
||||
.fav-toggle {
|
||||
margin-right: -12px;
|
||||
.icon {
|
||||
@include scale(1,1);
|
||||
@include scale(1, 1);
|
||||
@include opacity(1);
|
||||
}
|
||||
}
|
||||
@@ -384,7 +406,7 @@
|
||||
|
||||
> a {
|
||||
/* aspect ratio without spacer image */
|
||||
&:before{
|
||||
&:before {
|
||||
content: "";
|
||||
display: block;
|
||||
padding-top: 100%; /* initial ratio of 1:1*/
|
||||
@@ -392,9 +414,11 @@
|
||||
}
|
||||
|
||||
background-color: white;
|
||||
border-radius: $radius*2;
|
||||
border-radius: $radius * 2;
|
||||
|
||||
&:active { opacity: 0.95 !important; }
|
||||
&:active {
|
||||
opacity: 0.95 !important;
|
||||
}
|
||||
|
||||
box-shadow: 0 0 30px 1px rgba(0, 0, 0, 0.15);
|
||||
border: 1px solid black;
|
||||
@@ -406,7 +430,7 @@
|
||||
font-weight: 400;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
border-radius: $radius*2;
|
||||
border-radius: $radius * 2;
|
||||
position: relative;
|
||||
|
||||
.item-thumbnail {
|
||||
@@ -420,8 +444,9 @@
|
||||
overflow: hidden;
|
||||
|
||||
background-color: transparent;
|
||||
border-top-left-radius: $radius*2;
|
||||
border-top-right-radius: $radius*2;
|
||||
background-size: cover;
|
||||
border-top-left-radius: $radius * 2;
|
||||
border-top-right-radius: $radius * 2;
|
||||
|
||||
border-bottom-left-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
@@ -431,7 +456,7 @@
|
||||
|
||||
.item-title {
|
||||
display: block;
|
||||
border-top: 1px solid rgba(0,0,0,0.05);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||
background-color: white;
|
||||
font-size: 18px;
|
||||
width: 100%;
|
||||
@@ -439,15 +464,15 @@
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
position: absolute;
|
||||
border-bottom-left-radius: $radius*2;
|
||||
border-bottom-right-radius: $radius*2;
|
||||
border-bottom-left-radius: $radius * 2;
|
||||
border-bottom-right-radius: $radius * 2;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: $dark;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
.thumbnail-loading {
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
@@ -464,11 +489,11 @@
|
||||
}
|
||||
|
||||
.item-meta {
|
||||
border-top: 2px solid rgba(0,0,0,0.025);
|
||||
border-radius: 2*$radius;
|
||||
border-top: 2px solid rgba(0, 0, 0, 0.025);
|
||||
border-radius: 2 * $radius;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
|
||||
|
||||
@include clearfix;
|
||||
color: $medium;
|
||||
position: absolute;
|
||||
@@ -493,8 +518,8 @@
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
position: relative;
|
||||
border-bottom-left-radius: $radius*2;
|
||||
border-bottom-right-radius: $radius*2;
|
||||
border-bottom-left-radius: $radius * 2;
|
||||
border-bottom-right-radius: $radius * 2;
|
||||
//white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -509,7 +534,7 @@
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: $folder-gutter*2;
|
||||
right: $folder-gutter * 2;
|
||||
color: $medium;
|
||||
font-size: 11px;
|
||||
font-family: $main-font;
|
||||
|
||||
Reference in New Issue
Block a user