mirror of
https://github.com/BookStackApp/BookStack.git
synced 2026-02-06 09:09:38 +03:00
Compare commits
155 Commits
fix/video-
...
v0.25.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25bc28a1be | ||
|
|
4c561c7fa0 | ||
|
|
12be7d0086 | ||
|
|
ba0af9214e | ||
|
|
36424a24b5 | ||
|
|
a70ee9664a | ||
|
|
156c0a88e9 | ||
|
|
95b3e78573 | ||
|
|
63a345bc93 | ||
|
|
a3ccde8698 | ||
|
|
9700b7ccea | ||
|
|
54c428c375 | ||
|
|
ebe5d643f3 | ||
|
|
e66ddbc17b | ||
|
|
0e0a17cc30 | ||
|
|
ffceb4092e | ||
|
|
50e5527483 | ||
|
|
f63fd4beca | ||
|
|
d682a0157f | ||
|
|
70ad707c3c | ||
|
|
3062bf1876 | ||
|
|
a2087fe3ff | ||
|
|
2c48f4f7e8 | ||
|
|
e093a172cb | ||
|
|
4b01f8934b | ||
|
|
3c796b1ae7 | ||
|
|
b7915cc7b0 | ||
|
|
54b36cd305 | ||
|
|
bc116b45b5 | ||
|
|
a059960b9e | ||
|
|
7770966fed | ||
|
|
d7adcf6c69 | ||
|
|
04a364dcc3 | ||
|
|
db83ac7eaa | ||
|
|
3ca9dddf61 | ||
|
|
bf74f53ca7 | ||
|
|
9d67efb4a4 | ||
|
|
3a39b9f440 | ||
|
|
27f7aab375 | ||
|
|
337da0c467 | ||
|
|
f56b3560c4 | ||
|
|
02dfe11ce6 | ||
|
|
83d06beb70 | ||
|
|
a8cfc059c8 | ||
|
|
1614b2bab0 | ||
|
|
4bdec0d214 | ||
|
|
6a7d7e7c2b | ||
|
|
30d4674657 | ||
|
|
9f961f95f8 | ||
|
|
bab99a26ec | ||
|
|
9a7fecd269 | ||
|
|
a8dc0d449b | ||
|
|
a0381f76bf | ||
|
|
6102f66daa | ||
|
|
c6134d162d | ||
|
|
2046f9b9de | ||
|
|
ac3ba594a4 | ||
|
|
22df25a480 | ||
|
|
8b30c7f02e | ||
|
|
757cdddc7c | ||
|
|
df95e99680 | ||
|
|
5a6d544db7 | ||
|
|
16117d329c | ||
|
|
e90da18ada | ||
|
|
a08d80e1cc | ||
|
|
6258175922 | ||
|
|
15736777a0 | ||
|
|
75915e8a94 | ||
|
|
9bde0ae4ea | ||
|
|
0c802d1f86 | ||
|
|
b7a96c6466 | ||
|
|
4b645a82c7 | ||
|
|
d599b77b6f | ||
|
|
26e93dc8c1 | ||
|
|
a4c9a8491b | ||
|
|
70ee636d87 | ||
|
|
b35f6dbb03 | ||
|
|
67d9e24d8f | ||
|
|
3903fda6ca | ||
|
|
441e46ebaa | ||
|
|
1f4260f359 | ||
|
|
dc0bf8ad4e | ||
|
|
102e326e6a | ||
|
|
2b25bf6f3b | ||
|
|
f93280696d | ||
|
|
1787391b07 | ||
|
|
a74a8ee483 | ||
|
|
7fa5405cb7 | ||
|
|
6725ddcc41 | ||
|
|
bce941db3f | ||
|
|
6d926048ec | ||
|
|
5335c973b4 | ||
|
|
15c3e5c96e | ||
|
|
a5d5904969 | ||
|
|
598758b991 | ||
|
|
9926e23bc8 | ||
|
|
5d3264bc63 | ||
|
|
d71f819f95 | ||
|
|
ee13509760 | ||
|
|
82d7bb1f32 | ||
|
|
cdfda508d8 | ||
|
|
da941e584f | ||
|
|
65874d7b96 | ||
|
|
ac9b8f405c | ||
|
|
8d1419a12e | ||
|
|
04f7a7d301 | ||
|
|
c10d2a1493 | ||
|
|
97bbf79ffd | ||
|
|
f7b01ae53d | ||
|
|
d704e1dbba | ||
|
|
ef2ff5e093 | ||
|
|
7caed3b0db | ||
|
|
45641d0754 | ||
|
|
4b1d08ba99 | ||
|
|
160fa99ba4 | ||
|
|
d2a5ab49ed | ||
|
|
c6404d8917 | ||
|
|
7113807f12 | ||
|
|
be711215e8 | ||
|
|
7e3b404240 | ||
|
|
e86901ca20 | ||
|
|
bdfa61c8b2 | ||
|
|
2cc36787f5 | ||
|
|
448ac61b48 | ||
|
|
753f6394f7 | ||
|
|
b1faf65934 | ||
|
|
09f478bd74 | ||
|
|
a0497feddd | ||
|
|
789693bde9 | ||
|
|
1fe933e4ea | ||
|
|
724b4b5a70 | ||
|
|
1778a56146 | ||
|
|
744865fcb2 | ||
|
|
7f8c8b448d | ||
|
|
a67c53826d | ||
|
|
14b131e850 | ||
|
|
9b55a52b85 | ||
|
|
db1d10e80f | ||
|
|
1be576966f | ||
|
|
b97e792c5f | ||
|
|
8dec674cc3 | ||
|
|
f784c03746 | ||
|
|
148e172fe8 | ||
|
|
56ae86646f | ||
|
|
1d2b6fdfa2 | ||
|
|
4fc75beed4 | ||
|
|
3b3bc0c4bf | ||
|
|
910faab88e | ||
|
|
f184d763ad | ||
|
|
a91d42634d | ||
|
|
f517ef3616 | ||
|
|
e99507ddcf | ||
|
|
d2cacf1945 | ||
|
|
448ac1405b | ||
|
|
6ad21ce885 |
97
.env.example
97
.env.example
@@ -1,11 +1,14 @@
|
||||
# Environment
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
# Application key
|
||||
# Used for encryption where needed.
|
||||
# Run `php artisan key:generate` to generate a valid key.
|
||||
APP_KEY=SomeRandomString
|
||||
|
||||
# The below url has to be set if using social auth options
|
||||
# or if you are not using BookStack at the root path of your domain.
|
||||
# APP_URL=http://bookstack.dev
|
||||
# Application URL
|
||||
# Remove the hash below and set a URL if using BookStack behind
|
||||
# a proxy, if using a third-party authentication option.
|
||||
# This must be the root URL that you want to host BookStack on.
|
||||
# All URL's in BookStack will be generated using this value.
|
||||
#APP_URL=https://example.com
|
||||
|
||||
# Database details
|
||||
DB_HOST=localhost
|
||||
@@ -13,84 +16,16 @@ DB_DATABASE=database_database
|
||||
DB_USERNAME=database_username
|
||||
DB_PASSWORD=database_user_password
|
||||
|
||||
# Cache and session
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
# If using Memcached, comment the above and uncomment these
|
||||
#CACHE_DRIVER=memcached
|
||||
#SESSION_DRIVER=memcached
|
||||
QUEUE_DRIVER=sync
|
||||
# A different prefix is useful when multiple BookStack instances use the same caching server
|
||||
CACHE_PREFIX=bookstack
|
||||
|
||||
# Memcached settings
|
||||
# If using a UNIX socket path for the host, set the port to 0
|
||||
# This follows the following format: HOST:PORT:WEIGHT
|
||||
# For multiple servers separate with a comma
|
||||
MEMCACHED_SERVERS=127.0.0.1:11211:100
|
||||
|
||||
# Storage
|
||||
STORAGE_TYPE=local
|
||||
# Amazon S3 Config
|
||||
STORAGE_S3_KEY=false
|
||||
STORAGE_S3_SECRET=false
|
||||
STORAGE_S3_REGION=false
|
||||
STORAGE_S3_BUCKET=false
|
||||
# Storage URL
|
||||
# Used to prefix image urls for when using custom domains/cdns
|
||||
STORAGE_URL=false
|
||||
|
||||
# General auth
|
||||
AUTH_METHOD=standard
|
||||
|
||||
# Social Authentication information. Defaults as off.
|
||||
GITHUB_APP_ID=false
|
||||
GITHUB_APP_SECRET=false
|
||||
GOOGLE_APP_ID=false
|
||||
GOOGLE_APP_SECRET=false
|
||||
GOOGLE_SELECT_ACCOUNT=false
|
||||
OKTA_BASE_URL=false
|
||||
OKTA_APP_ID=false
|
||||
OKTA_APP_SECRET=false
|
||||
TWITCH_APP_ID=false
|
||||
TWITCH_APP_SECRET=false
|
||||
GITLAB_APP_ID=false
|
||||
GITLAB_APP_SECRET=false
|
||||
GITLAB_BASE_URI=false
|
||||
DISCORD_APP_ID=false
|
||||
DISCORD_APP_SECRET=false
|
||||
|
||||
|
||||
# Disable default services such as Gravatar and Draw.IO
|
||||
DISABLE_EXTERNAL_SERVICES=false
|
||||
# Use custom avatar service, Sets fetch URL
|
||||
# Possible placeholders: ${hash} ${size} ${email}
|
||||
# If set, Avatars will be fetched regardless of DISABLE_EXTERNAL_SERVICES option.
|
||||
# AVATAR_URL=https://seccdn.libravatar.org/avatar/${hash}?s=${size}&d=identicon
|
||||
|
||||
# LDAP Settings
|
||||
LDAP_SERVER=false
|
||||
LDAP_BASE_DN=false
|
||||
LDAP_DN=false
|
||||
LDAP_PASS=false
|
||||
LDAP_USER_FILTER=false
|
||||
LDAP_VERSION=false
|
||||
# Do you want to sync LDAP groups to BookStack roles for a user
|
||||
LDAP_USER_TO_GROUPS=false
|
||||
# What is the LDAP attribute for group memberships
|
||||
LDAP_GROUP_ATTRIBUTE="memberOf"
|
||||
# Would you like to remove users from roles on BookStack if they do not match on LDAP
|
||||
# If false, the ldap groups-roles sync will only add users to roles
|
||||
LDAP_REMOVE_FROM_GROUPS=false
|
||||
# Set this option to disable LDAPS Certificate Verification
|
||||
LDAP_TLS_INSECURE=false
|
||||
|
||||
# Mail settings
|
||||
# Mail system to use
|
||||
# Can be 'smtp', 'mail' or 'sendmail'
|
||||
MAIL_DRIVER=smtp
|
||||
|
||||
# SMTP mail options
|
||||
MAIL_HOST=localhost
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM=null
|
||||
MAIL_FROM_NAME=null
|
||||
|
||||
|
||||
# A full list of options can be found in the '.env.example.complete' file.
|
||||
215
.env.example.complete
Normal file
215
.env.example.complete
Normal file
@@ -0,0 +1,215 @@
|
||||
# Full list of environment variables that can be used with BookStack.
|
||||
# Selectively copy these to your '.env' file as required.
|
||||
# Each option is shown with it's default value.
|
||||
# Do not copy this whole file to use as your '.env' file.
|
||||
|
||||
# Application environment
|
||||
# Can be 'production', 'development', 'testing' or 'demo'
|
||||
APP_ENV=production
|
||||
|
||||
# Enable debug mode
|
||||
# Shows advanced debug information and errors.
|
||||
# CAN EXPOSE OTHER VARIABLES, LEAVE DISABLED
|
||||
APP_DEBUG=false
|
||||
|
||||
# Application key
|
||||
# Used for encryption where needed.
|
||||
# Run `php artisan key:generate` to generate a valid key.
|
||||
APP_KEY=SomeRandomString
|
||||
|
||||
# Application URL
|
||||
# This must be the root URL that you want to host BookStack on.
|
||||
# All URL's in BookStack will be generated using this value.
|
||||
APP_URL=https://example.com
|
||||
|
||||
# Application default language
|
||||
# The default language choice to show.
|
||||
# May be overridden by user-preference or visitor browser settings.
|
||||
APP_LANG=en
|
||||
|
||||
# Auto-detect language for public visitors.
|
||||
# Uses browser-sent headers to infer a language.
|
||||
# APP_LANG will be used if such a header is not provided.
|
||||
APP_AUTO_LANG_PUBLIC=true
|
||||
|
||||
# Database details
|
||||
# Host can contain a port (localhost:3306) or a separate DB_PORT option can be used.
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=database_database
|
||||
DB_USERNAME=database_username
|
||||
DB_PASSWORD=database_user_password
|
||||
|
||||
# Mail system to use
|
||||
# Can be 'smtp', 'mail' or 'sendmail'
|
||||
MAIL_DRIVER=smtp
|
||||
|
||||
# Mail sending options
|
||||
MAIL_FROM=mail@bookstackapp.com
|
||||
MAIL_FROM_NAME=BookStack
|
||||
|
||||
# SMTP mail options
|
||||
MAIL_HOST=localhost
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
|
||||
# Cache & Session driver to use
|
||||
# Can be 'file', 'database', 'memcached' or 'redis'
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# Session configuration
|
||||
SESSION_LIFETIME=120
|
||||
SESSION_COOKIE_NAME=bookstack_session
|
||||
SESSION_SECURE_COOKIE=false
|
||||
|
||||
# Cache key prefix
|
||||
# Can be used to prevent conflicts multiple BookStack instances use the same store.
|
||||
CACHE_PREFIX=bookstack
|
||||
|
||||
# Memcached server configuration
|
||||
# If using a UNIX socket path for the host, set the port to 0
|
||||
# This follows the following format: HOST:PORT:WEIGHT
|
||||
# For multiple servers separate with a comma
|
||||
MEMCACHED_SERVERS=127.0.0.1:11211:100
|
||||
|
||||
# Queue driver to use
|
||||
# Queue not really currently used but may be configurable in the future.
|
||||
# Would advise not to change this for now.
|
||||
QUEUE_DRIVER=sync
|
||||
|
||||
# Storage system to use
|
||||
# Can be 'local', 'local_secure' or 's3'
|
||||
STORAGE_TYPE=local
|
||||
|
||||
# Amazon S3 storage configuration
|
||||
STORAGE_S3_KEY=your-s3-key
|
||||
STORAGE_S3_SECRET=your-s3-secret
|
||||
STORAGE_S3_BUCKET=s3-bucket-name
|
||||
STORAGE_S3_REGION=s3-bucket-region
|
||||
|
||||
# S3 endpoint to use for storage calls
|
||||
# Only set this if using a non-Amazon s3-compatible service such as Minio
|
||||
STORAGE_S3_ENDPOINT=https://my-custom-s3-compatible.service.com:8001
|
||||
|
||||
# Storage URL prefix
|
||||
# Used as a base for any generated image urls.
|
||||
# An s3-format URL will be generated if not set.
|
||||
STORAGE_URL=false
|
||||
|
||||
# Authentication method to use
|
||||
# Can be 'standard' or 'ldap'
|
||||
AUTH_METHOD=standard
|
||||
|
||||
# Social authentication configuration
|
||||
# All disabled by default.
|
||||
# Refer to https://www.bookstackapp.com/docs/admin/third-party-auth/
|
||||
|
||||
AZURE_APP_ID=false
|
||||
AZURE_APP_SECRET=false
|
||||
AZURE_TENANT=false
|
||||
AZURE_AUTO_REGISTER=false
|
||||
AZURE_AUTO_CONFIRM_EMAIL=false
|
||||
|
||||
DISCORD_APP_ID=false
|
||||
DISCORD_APP_SECRET=false
|
||||
DISCORD_AUTO_REGISTER=false
|
||||
DISCORD_AUTO_CONFIRM_EMAIL=false
|
||||
|
||||
FACEBOOK_APP_ID=false
|
||||
FACEBOOK_APP_SECRET=false
|
||||
FACEBOOK_AUTO_REGISTER=false
|
||||
FACEBOOK_AUTO_CONFIRM_EMAIL=false
|
||||
|
||||
GITHUB_APP_ID=false
|
||||
GITHUB_APP_SECRET=false
|
||||
GITHUB_AUTO_REGISTER=false
|
||||
GITHUB_AUTO_CONFIRM_EMAIL=false
|
||||
|
||||
GITLAB_APP_ID=false
|
||||
GITLAB_APP_SECRET=false
|
||||
GITLAB_BASE_URI=false
|
||||
GITLAB_AUTO_REGISTER=false
|
||||
GITLAB_AUTO_CONFIRM_EMAIL=false
|
||||
|
||||
GOOGLE_APP_ID=false
|
||||
GOOGLE_APP_SECRET=false
|
||||
GOOGLE_SELECT_ACCOUNT=false
|
||||
GOOGLE_AUTO_REGISTER=false
|
||||
GOOGLE_AUTO_CONFIRM_EMAIL=false
|
||||
|
||||
OKTA_BASE_URL=false
|
||||
OKTA_APP_ID=false
|
||||
OKTA_APP_SECRET=false
|
||||
OKTA_AUTO_REGISTER=false
|
||||
OKTA_AUTO_CONFIRM_EMAIL=false
|
||||
|
||||
SLACK_APP_ID=false
|
||||
SLACK_APP_SECRET=false
|
||||
SLACK_AUTO_REGISTER=false
|
||||
SLACK_AUTO_CONFIRM_EMAIL=false
|
||||
|
||||
TWITCH_APP_ID=false
|
||||
TWITCH_APP_SECRET=false
|
||||
TWITCH_AUTO_REGISTER=false
|
||||
TWITCH_AUTO_CONFIRM_EMAIL=false
|
||||
|
||||
TWITTER_APP_ID=false
|
||||
TWITTER_APP_SECRET=false
|
||||
TWITTER_AUTO_REGISTER=false
|
||||
TWITTER_AUTO_CONFIRM_EMAIL=false
|
||||
|
||||
# LDAP authentication configuration
|
||||
# Refer to https://www.bookstackapp.com/docs/admin/ldap-auth/
|
||||
LDAP_SERVER=false
|
||||
LDAP_BASE_DN=false
|
||||
LDAP_DN=false
|
||||
LDAP_PASS=false
|
||||
LDAP_USER_FILTER=false
|
||||
LDAP_VERSION=false
|
||||
LDAP_TLS_INSECURE=false
|
||||
LDAP_EMAIL_ATTRIBUTE=mail
|
||||
LDAP_FOLLOW_REFERRALS=true
|
||||
|
||||
# LDAP group sync configuration
|
||||
# Refer to https://www.bookstackapp.com/docs/admin/ldap-auth/
|
||||
LDAP_USER_TO_GROUPS=false
|
||||
LDAP_GROUP_ATTRIBUTE="memberOf"
|
||||
LDAP_REMOVE_FROM_GROUPS=false
|
||||
|
||||
# Disable default third-party services such as Gravatar and Draw.IO
|
||||
# Service-specific options will override this option
|
||||
DISABLE_EXTERNAL_SERVICES=false
|
||||
|
||||
# Use custom avatar service, Sets fetch URL
|
||||
# Possible placeholders: ${hash} ${size} ${email}
|
||||
# If set, Avatars will be fetched regardless of DISABLE_EXTERNAL_SERVICES option.
|
||||
# Example: AVATAR_URL=https://seccdn.libravatar.org/avatar/${hash}?s=${size}&d=identicon
|
||||
AVATAR_URL=
|
||||
|
||||
# Enable Draw.io integration
|
||||
DRAWIO=true
|
||||
|
||||
# Default item listing view
|
||||
# Used for public visitors and user's without a preference
|
||||
# Can be 'list' or 'grid'
|
||||
APP_VIEWS_BOOKS=list
|
||||
APP_VIEWS_BOOKSHELVES=grid
|
||||
|
||||
# Page revision limit
|
||||
# Number of page revisions to keep in the system before deleting old revisions.
|
||||
# If set to 'false' a limit will not be enforced.
|
||||
REVISION_LIMIT=50
|
||||
|
||||
# Allow <script> tags in page content
|
||||
# Note, if set to 'true' the page editor may still escape scripts.
|
||||
ALLOW_CONTENT_SCRIPTS=false
|
||||
|
||||
# Indicate if robots/crawlers should crawl your instance.
|
||||
# Can be 'true', 'false' or 'null'.
|
||||
# The behaviour of the default 'null' option will depend on the 'app-public' admin setting.
|
||||
# Contents of the robots.txt file can be overridden, making this option obsolete.
|
||||
ALLOW_ROBOTS=null
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -5,10 +5,10 @@ Homestead.yaml
|
||||
.idea
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
/public/dist
|
||||
/public/dist/*.map
|
||||
/public/plugins
|
||||
/public/css
|
||||
/public/js
|
||||
/public/css/*.map
|
||||
/public/js/*.map
|
||||
/public/bower
|
||||
/public/build/
|
||||
/storage/images
|
||||
|
||||
@@ -599,24 +599,48 @@ class EntityRepo
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the page for viewing, Parsing and performing features such as page transclusion.
|
||||
* Render the page for viewing
|
||||
* @param Page $page
|
||||
* @param bool $ignorePermissions
|
||||
* @return mixed|string
|
||||
* @param bool $blankIncludes
|
||||
* @return string
|
||||
*/
|
||||
public function renderPage(Page $page, $ignorePermissions = false)
|
||||
public function renderPage(Page $page, bool $blankIncludes = false) : string
|
||||
{
|
||||
$content = $page->html;
|
||||
|
||||
if (!config('app.allow_content_scripts')) {
|
||||
$content = $this->escapeScripts($content);
|
||||
}
|
||||
|
||||
$matches = [];
|
||||
preg_match_all("/{{@\s?([0-9].*?)}}/", $content, $matches);
|
||||
if (count($matches[0]) === 0) {
|
||||
return $content;
|
||||
if ($blankIncludes) {
|
||||
$content = $this->blankPageIncludes($content);
|
||||
} else {
|
||||
$content = $this->parsePageIncludes($content);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any page include tags within the given HTML.
|
||||
* @param string $html
|
||||
* @return string
|
||||
*/
|
||||
protected function blankPageIncludes(string $html) : string
|
||||
{
|
||||
return preg_replace("/{{@\s?([0-9].*?)}}/", '', $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse any include tags "{{@<page_id>#section}}" to be part of the page.
|
||||
* @param string $html
|
||||
* @return mixed|string
|
||||
*/
|
||||
protected function parsePageIncludes(string $html) : string
|
||||
{
|
||||
$matches = [];
|
||||
preg_match_all("/{{@\s?([0-9].*?)}}/", $html, $matches);
|
||||
|
||||
$topLevelTags = ['table', 'ul', 'ol'];
|
||||
foreach ($matches[1] as $index => $includeId) {
|
||||
$splitInclude = explode('#', $includeId, 2);
|
||||
@@ -625,14 +649,14 @@ class EntityRepo
|
||||
continue;
|
||||
}
|
||||
|
||||
$matchedPage = $this->getById('page', $pageId, false, $ignorePermissions);
|
||||
$matchedPage = $this->getById('page', $pageId);
|
||||
if ($matchedPage === null) {
|
||||
$content = str_replace($matches[0][$index], '', $content);
|
||||
$html = str_replace($matches[0][$index], '', $html);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count($splitInclude) === 1) {
|
||||
$content = str_replace($matches[0][$index], $matchedPage->html, $content);
|
||||
$html = str_replace($matches[0][$index], $matchedPage->html, $html);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -640,7 +664,7 @@ class EntityRepo
|
||||
$doc->loadHTML(mb_convert_encoding('<body>'.$matchedPage->html.'</body>', 'HTML-ENTITIES', 'UTF-8'));
|
||||
$matchingElem = $doc->getElementById($splitInclude[1]);
|
||||
if ($matchingElem === null) {
|
||||
$content = str_replace($matches[0][$index], '', $content);
|
||||
$html = str_replace($matches[0][$index], '', $html);
|
||||
continue;
|
||||
}
|
||||
$innerContent = '';
|
||||
@@ -652,25 +676,22 @@ class EntityRepo
|
||||
$innerContent .= $doc->saveHTML($childNode);
|
||||
}
|
||||
}
|
||||
$content = str_replace($matches[0][$index], trim($innerContent), $content);
|
||||
$html = str_replace($matches[0][$index], trim($innerContent), $html);
|
||||
}
|
||||
|
||||
return $content;
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape script tags within HTML content.
|
||||
* @param string $html
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
protected function escapeScripts(string $html)
|
||||
protected function escapeScripts(string $html) : string
|
||||
{
|
||||
$scriptSearchRegex = '/<script.*?>.*?<\/script>/ms';
|
||||
$matches = [];
|
||||
preg_match_all($scriptSearchRegex, $html, $matches);
|
||||
if (count($matches) === 0) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
foreach ($matches[0] as $match) {
|
||||
$html = str_replace($match, htmlentities($match), $html);
|
||||
|
||||
@@ -194,9 +194,9 @@ class PageRepo extends EntityRepo
|
||||
* @param \BookStack\Entities\Page $page
|
||||
* @return string
|
||||
*/
|
||||
public function pageToPlainText(Page $page)
|
||||
protected function pageToPlainText(Page $page) : string
|
||||
{
|
||||
$html = $this->renderPage($page);
|
||||
$html = $this->renderPage($page, true);
|
||||
return strip_tags($html);
|
||||
}
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ class ChapterController extends Controller
|
||||
$chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
|
||||
$this->setPageTitle(trans('entities.chapters_move_named', ['chapterName' => $chapter->getShortName()]));
|
||||
$this->checkOwnablePermission('chapter-update', $chapter);
|
||||
$this->checkOwnablePermission('chapter-delete', $chapter);
|
||||
return view('chapters/move', [
|
||||
'chapter' => $chapter,
|
||||
'book' => $chapter->book
|
||||
@@ -179,6 +180,7 @@ class ChapterController extends Controller
|
||||
{
|
||||
$chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
|
||||
$this->checkOwnablePermission('chapter-update', $chapter);
|
||||
$this->checkOwnablePermission('chapter-delete', $chapter);
|
||||
|
||||
$entitySelection = $request->get('entity_selection', null);
|
||||
if ($entitySelection === null || $entitySelection === '') {
|
||||
|
||||
@@ -586,6 +586,7 @@ class PageController extends Controller
|
||||
{
|
||||
$page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug);
|
||||
$this->checkOwnablePermission('page-update', $page);
|
||||
$this->checkOwnablePermission('page-delete', $page);
|
||||
return view('pages/move', [
|
||||
'book' => $page->book,
|
||||
'page' => $page
|
||||
@@ -604,6 +605,7 @@ class PageController extends Controller
|
||||
{
|
||||
$page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug);
|
||||
$this->checkOwnablePermission('page-update', $page);
|
||||
$this->checkOwnablePermission('page-delete', $page);
|
||||
|
||||
$entitySelection = $request->get('entity_selection', null);
|
||||
if ($entitySelection === null || $entitySelection === '') {
|
||||
|
||||
@@ -7,8 +7,40 @@ use Illuminate\Http\Request;
|
||||
class Localization
|
||||
{
|
||||
|
||||
/**
|
||||
* Array of right-to-left locales
|
||||
* @var array
|
||||
*/
|
||||
protected $rtlLocales = ['ar'];
|
||||
|
||||
/**
|
||||
* Map of BookStack locale names to best-estimate system locale names.
|
||||
* @var array
|
||||
*/
|
||||
protected $localeMap = [
|
||||
'ar' => 'ar',
|
||||
'de' => 'de_DE',
|
||||
'de_informal' => 'de_DE',
|
||||
'en' => 'en_GB',
|
||||
'es' => 'es_ES',
|
||||
'es_AR' => 'es_AR',
|
||||
'fr' => 'fr_FR',
|
||||
'it' => 'it_IT',
|
||||
'ja' => 'ja',
|
||||
'kr' => 'ko_KR',
|
||||
'nl' => 'nl_NL',
|
||||
'pl' => 'pl_PL',
|
||||
'pt_BR' => 'pt_BR',
|
||||
'pt_BR' => 'pt_BR',
|
||||
'ru' => 'ru',
|
||||
'sk' => 'sk_SK',
|
||||
'sv' => 'sv_SE',
|
||||
'uk' => 'uk_UA',
|
||||
'uk' => 'uk_UA',
|
||||
'zh_CN' => 'zh_CN',
|
||||
'zh_TW' => 'zh_TW',
|
||||
];
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
@@ -31,8 +63,11 @@ class Localization
|
||||
config()->set('app.rtl', true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
app()->setLocale($locale);
|
||||
Carbon::setLocale($locale);
|
||||
$this->setSystemDateLocale($locale);
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
@@ -53,4 +88,18 @@ class Localization
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the system date locale for localized date formatting.
|
||||
* Will try both the standard locale name and the UTF8 variant.
|
||||
* @param string $locale
|
||||
*/
|
||||
protected function setSystemDateLocale(string $locale)
|
||||
{
|
||||
$systemLocale = $this->localeMap[$locale] ?? $locale;
|
||||
$set = setlocale(LC_TIME, $systemLocale);
|
||||
if ($set === false) {
|
||||
setlocale(LC_TIME, $systemLocale . '.utf8');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"laravel/framework": "~5.5.44",
|
||||
"fideloper/proxy": "~3.3",
|
||||
"intervention/image": "^2.4",
|
||||
"laravel/socialite": "^3.0",
|
||||
"laravel/socialite": "3.0.x-dev",
|
||||
"league/flysystem-aws-s3-v3": "^1.0",
|
||||
"barryvdh/laravel-dompdf": "^0.8.1",
|
||||
"predis/predis": "^1.1",
|
||||
|
||||
93
composer.lock
generated
93
composer.lock
generated
@@ -4,20 +4,20 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "06219a5c2419ca23ec2924eb31f4ed16",
|
||||
"content-hash": "0946a07729a7a1bfef9bac185a870afd",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.82.3",
|
||||
"version": "3.86.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "a0353c24b18d2ba0f5bb7ca8a478b4ce0b8153f7"
|
||||
"reference": "50224232ac7a4e2a6fa4ebbe0281e5b7503acf76"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a0353c24b18d2ba0f5bb7ca8a478b4ce0b8153f7",
|
||||
"reference": "a0353c24b18d2ba0f5bb7ca8a478b4ce0b8153f7",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/50224232ac7a4e2a6fa4ebbe0281e5b7503acf76",
|
||||
"reference": "50224232ac7a4e2a6fa4ebbe0281e5b7503acf76",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -87,7 +87,7 @@
|
||||
"s3",
|
||||
"sdk"
|
||||
],
|
||||
"time": "2018-12-21T22:21:50+00:00"
|
||||
"time": "2019-01-18T21:10:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "barryvdh/laravel-dompdf",
|
||||
@@ -1457,16 +1457,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/socialite",
|
||||
"version": "v3.2.0",
|
||||
"version": "3.0.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/socialite.git",
|
||||
"reference": "7194c0cd9fb2ce449669252b8ec316b85b7de481"
|
||||
"reference": "79316f36641f1916a50ab14d368acdf1d97e46de"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/socialite/zipball/7194c0cd9fb2ce449669252b8ec316b85b7de481",
|
||||
"reference": "7194c0cd9fb2ce449669252b8ec316b85b7de481",
|
||||
"url": "https://api.github.com/repos/laravel/socialite/zipball/79316f36641f1916a50ab14d368acdf1d97e46de",
|
||||
"reference": "79316f36641f1916a50ab14d368acdf1d97e46de",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1516,7 +1516,7 @@
|
||||
"laravel",
|
||||
"oauth"
|
||||
],
|
||||
"time": "2018-10-18T03:39:04+00:00"
|
||||
"time": "2018-12-21T14:06:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem",
|
||||
@@ -1891,16 +1891,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "1.36.1",
|
||||
"version": "1.36.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/briannesbitt/Carbon.git",
|
||||
"reference": "63da8cdf89d7a5efe43aabc794365f6e7b7b8983"
|
||||
"reference": "cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/63da8cdf89d7a5efe43aabc794365f6e7b7b8983",
|
||||
"reference": "63da8cdf89d7a5efe43aabc794365f6e7b7b8983",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9",
|
||||
"reference": "cd324b98bc30290f233dd0e75e6ce49f7ab2a6c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1945,7 +1945,7 @@
|
||||
"datetime",
|
||||
"time"
|
||||
],
|
||||
"time": "2018-11-22T18:23:02+00:00"
|
||||
"time": "2018-12-28T10:07:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/random_compat",
|
||||
@@ -2555,20 +2555,20 @@
|
||||
},
|
||||
{
|
||||
"name": "socialiteproviders/manager",
|
||||
"version": "v3.3.1",
|
||||
"version": "v3.3.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/SocialiteProviders/Manager.git",
|
||||
"reference": "1de3f3d874392da6f1a4c0bf30d843e9cd903ea7"
|
||||
"reference": "58b72a667da292a1d0a0b1e6e9aeda4053617030"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/1de3f3d874392da6f1a4c0bf30d843e9cd903ea7",
|
||||
"reference": "1de3f3d874392da6f1a4c0bf30d843e9cd903ea7",
|
||||
"url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/58b72a667da292a1d0a0b1e6e9aeda4053617030",
|
||||
"reference": "58b72a667da292a1d0a0b1e6e9aeda4053617030",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"laravel/socialite": "~3.0",
|
||||
"laravel/socialite": "~3.0|~4.0",
|
||||
"php": "^5.6 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -2585,8 +2585,7 @@
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"SocialiteProviders\\Manager\\": "src/",
|
||||
"SocialiteProviders\\Manager\\Test\\": "tests/"
|
||||
"SocialiteProviders\\Manager\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
@@ -2597,10 +2596,14 @@
|
||||
{
|
||||
"name": "Andy Wendt",
|
||||
"email": "andy@awendt.com"
|
||||
},
|
||||
{
|
||||
"name": "Anton Komarev",
|
||||
"email": "a.komarev@cybercog.su"
|
||||
}
|
||||
],
|
||||
"description": "Easily add new or override built-in providers in Laravel Socialite.",
|
||||
"time": "2017-11-20T08:42:57+00:00"
|
||||
"time": "2019-01-16T07:58:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "socialiteproviders/microsoft-azure",
|
||||
@@ -3664,16 +3667,16 @@
|
||||
},
|
||||
{
|
||||
"name": "vlucas/phpdotenv",
|
||||
"version": "v2.5.1",
|
||||
"version": "v2.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vlucas/phpdotenv.git",
|
||||
"reference": "8abb4f9aa89ddea9d52112c65bbe8d0125e2fa8e"
|
||||
"reference": "cfd5dc225767ca154853752abc93aeec040fcf36"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/8abb4f9aa89ddea9d52112c65bbe8d0125e2fa8e",
|
||||
"reference": "8abb4f9aa89ddea9d52112c65bbe8d0125e2fa8e",
|
||||
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/cfd5dc225767ca154853752abc93aeec040fcf36",
|
||||
"reference": "cfd5dc225767ca154853752abc93aeec040fcf36",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3710,7 +3713,7 @@
|
||||
"env",
|
||||
"environment"
|
||||
],
|
||||
"time": "2018-07-29T20:33:41+00:00"
|
||||
"time": "2018-10-30T17:29:25+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
@@ -4423,23 +4426,23 @@
|
||||
},
|
||||
{
|
||||
"name": "justinrainbow/json-schema",
|
||||
"version": "5.2.7",
|
||||
"version": "5.2.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/justinrainbow/json-schema.git",
|
||||
"reference": "8560d4314577199ba51bf2032f02cd1315587c23"
|
||||
"reference": "dcb6e1006bb5fd1e392b4daa68932880f37550d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8560d4314577199ba51bf2032f02cd1315587c23",
|
||||
"reference": "8560d4314577199ba51bf2032f02cd1315587c23",
|
||||
"url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/dcb6e1006bb5fd1e392b4daa68932880f37550d4",
|
||||
"reference": "dcb6e1006bb5fd1e392b4daa68932880f37550d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.1",
|
||||
"friendsofphp/php-cs-fixer": "~2.2.20",
|
||||
"json-schema/json-schema-test-suite": "1.2.0",
|
||||
"phpunit/phpunit": "^4.8.35"
|
||||
},
|
||||
@@ -4485,7 +4488,7 @@
|
||||
"json",
|
||||
"schema"
|
||||
],
|
||||
"time": "2018-02-14T22:26:30+00:00"
|
||||
"time": "2019-01-14T23:55:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/browser-kit-testing",
|
||||
@@ -6265,20 +6268,21 @@
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
"version": "1.3.0",
|
||||
"version": "1.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webmozart/assert.git",
|
||||
"reference": "0df1908962e7a3071564e857d86874dad1ef204a"
|
||||
"reference": "83e253c8e0be5b0257b881e1827274667c5c17a9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a",
|
||||
"reference": "0df1908962e7a3071564e857d86874dad1ef204a",
|
||||
"url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9",
|
||||
"reference": "83e253c8e0be5b0257b881e1827274667c5c17a9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.3.3 || ^7.0"
|
||||
"php": "^5.3.3 || ^7.0",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.6",
|
||||
@@ -6311,12 +6315,14 @@
|
||||
"check",
|
||||
"validate"
|
||||
],
|
||||
"time": "2018-01-29T19:49:41+00:00"
|
||||
"time": "2018-12-25T11:19:39+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {
|
||||
"laravel/socialite": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
@@ -6326,7 +6332,8 @@
|
||||
"ext-dom": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-gd": "*"
|
||||
"ext-gd": "*",
|
||||
"ext-curl": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"platform-overrides": {
|
||||
|
||||
@@ -22,7 +22,8 @@ return [
|
||||
// Set the default view type for various lists. Can be overridden by user preferences.
|
||||
// These will be used for public viewers and users that have not set a preference.
|
||||
'views' => [
|
||||
'books' => env('APP_VIEWS_BOOKS', 'list')
|
||||
'books' => env('APP_VIEWS_BOOKS', 'list'),
|
||||
'bookshelves' => env('APP_VIEWS_BOOKSHELVES', 'grid'),
|
||||
],
|
||||
|
||||
// The number of revisions to keep in the database.
|
||||
|
||||
@@ -49,6 +49,8 @@ return [
|
||||
'secret' => env('STORAGE_S3_SECRET', 'your-secret'),
|
||||
'region' => env('STORAGE_S3_REGION', 'your-region'),
|
||||
'bucket' => env('STORAGE_S3_BUCKET', 'your-bucket'),
|
||||
'endpoint' => env('STORAGE_S3_ENDPOINT', null),
|
||||
'use_path_style_endpoint' => env('STORAGE_S3_ENDPOINT', null) !== null,
|
||||
],
|
||||
|
||||
'rackspace' => [
|
||||
|
||||
@@ -14,7 +14,6 @@ return [
|
||||
// Options: file, cookie, database, redis, memcached, array
|
||||
'driver' => env('SESSION_DRIVER', 'file'),
|
||||
|
||||
|
||||
// Session lifetime, in minutes
|
||||
'lifetime' => env('SESSION_LIFETIME', 120),
|
||||
|
||||
|
||||
67
public/dist/app.js
vendored
Normal file
67
public/dist/app.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2516
public/dist/export-styles.css
vendored
Normal file
2516
public/dist/export-styles.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
34
public/dist/print-styles.css
vendored
Normal file
34
public/dist/print-styles.css
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
header {
|
||||
display: none; }
|
||||
|
||||
body {
|
||||
font-size: 12px; }
|
||||
|
||||
.faded-small {
|
||||
display: none; }
|
||||
|
||||
.page-content {
|
||||
margin: 0 auto; }
|
||||
|
||||
.flex-fill {
|
||||
display: block; }
|
||||
|
||||
.flex.sidebar + .flex.content {
|
||||
border-left: none; }
|
||||
|
||||
.print-hidden {
|
||||
display: none; }
|
||||
|
||||
.print-full-width {
|
||||
width: 100%;
|
||||
float: none;
|
||||
display: block; }
|
||||
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
line-height: 1;
|
||||
margin-top: 0.6em;
|
||||
margin-bottom: 0.3em; }
|
||||
|
||||
.comments-container {
|
||||
display: none; }
|
||||
4294
public/dist/styles.css
vendored
Normal file
4294
public/dist/styles.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
!function(){"use strict";var n=function(t){var e=t,r=function(){return e};return{get:r,set:function(t){e=t},clone:function(){return n(r())}}},t=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),o=tinymce.util.Tools.resolve("tinymce.util.Tools"),r=function(t){return t.fire("RestoreDraft")},i=function(t){return t.fire("StoreDraft")},s=function(t){return t.fire("RemoveDraft")},e=function(t,e){return((t=/^(\d+)([ms]?)$/.exec(""+(t||e)))[2]?{s:1e3,m:6e4}[t[2]]:1)*parseInt(t,10)},u=function(t){return t.getParam("autosave_ask_before_unload",!0)},f=function(t){var e=t.getParam("autosave_prefix","tinymce-autosave-{path}{query}{hash}-{id}-");return e=(e=(e=(e=e.replace(/\{path\}/g,document.location.pathname)).replace(/\{query\}/g,document.location.search)).replace(/\{hash\}/g,document.location.hash)).replace(/\{id\}/g,t.id)},c=function(t){return e(t.settings.autosave_interval,"30s")},l=function(t){return e(t.settings.autosave_retention,"20m")},m=function(t,e){var r=t.settings.forced_root_block;return""===(e=o.trim(void 0===e?t.getBody().innerHTML:e))||new RegExp("^<"+r+"[^>]*>((\xa0| |[ \t]|<br[^>]*>)+?|)</"+r+">|<br>$","i").test(e)},v=function(t){var e=parseInt(a.getItem(f(t)+"time"),10)||0;return!((new Date).getTime()-e>l(t)&&(d(t,!1),1))},d=function(t,e){var r=f(t);a.removeItem(r+"draft"),a.removeItem(r+"time"),!1!==e&&s(t)},D=function(t){var e=f(t);!m(t)&&t.isDirty()&&(a.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),a.setItem(e+"time",(new Date).getTime().toString()),i(t))},g=function(t){var e=f(t);v(t)&&(t.setContent(a.getItem(e+"draft"),{format:"raw"}),r(t))},y={isEmpty:m,hasDraft:v,removeDraft:d,storeDraft:D,restoreDraft:g,startStoreDraft:function(t,e){var r=c(t);e.get()||(setInterval(function(){t.removed||D(t)},r),e.set(!0))},restoreLastDraft:function(t){t.undoManager.transact(function(){g(t),d(t)}),t.focus()}},p=function(e,r){return function(){var t=Array.prototype.slice.call(arguments);return e.apply(null,[r].concat(t))}},h=function(t){return{hasDraft:p(y.hasDraft,t),storeDraft:p(y.storeDraft,t),restoreDraft:p(y.restoreDraft,t),removeDraft:p(y.removeDraft,t),isEmpty:p(y.isEmpty,t)}},_=tinymce.util.Tools.resolve("tinymce.EditorManager");_._beforeUnloadHandler=function(){var e;return o.each(_.get(),function(t){t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&u(t)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))}),e};var b=function(t){window.onbeforeunload=_._beforeUnloadHandler},I=function(r,n){return function(t){var e=t.control;e.disabled(!y.hasDraft(r)),r.on("StoreDraft RestoreDraft RemoveDraft",function(){e.disabled(!y.hasDraft(r))}),y.startStoreDraft(r,n)}},w=function(t,e){t.addButton("restoredraft",{title:"Restore last draft",onclick:function(){y.restoreLastDraft(t)},onPostRender:I(t,e)}),t.addMenuItem("restoredraft",{text:"Restore last draft",onclick:function(){y.restoreLastDraft(t)},onPostRender:I(t,e),context:"file"})};t.add("autosave",function(t){var e=n(!1);return b(t),w(t,e),h(t)})}();
|
||||
!function(){"use strict";var a=function(t){var e=t,n=function(){return e};return{get:n,set:function(t){e=t},clone:function(){return a(n())}}},t=tinymce.util.Tools.resolve("tinymce.PluginManager"),r=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),o=tinymce.util.Tools.resolve("tinymce.util.Tools"),i=function(t,e){var n=t||e,r=/^(\d+)([ms]?)$/.exec(""+n);return(r[2]?{s:1e3,m:6e4}[r[2]]:1)*parseInt(n,10)},u=function(t){var e=t.getParam("autosave_prefix","tinymce-autosave-{path}{query}{hash}-{id}-");return e=(e=(e=(e=e.replace(/\{path\}/g,document.location.pathname)).replace(/\{query\}/g,document.location.search)).replace(/\{hash\}/g,document.location.hash)).replace(/\{id\}/g,t.id)},s=function(t,e){var n=t.settings.forced_root_block;return""===(e=o.trim(void 0===e?t.getBody().innerHTML:e))||new RegExp("^<"+n+"[^>]*>((\xa0| |[ \t]|<br[^>]*>)+?|)</"+n+">|<br>$","i").test(e)},c=function(t){var e=parseInt(r.getItem(u(t)+"time"),10)||0;return!((new Date).getTime()-e>i(t.settings.autosave_retention,"20m")&&(f(t,!1),1))},f=function(t,e){var n=u(t);r.removeItem(n+"draft"),r.removeItem(n+"time"),!1!==e&&t.fire("RemoveDraft")},l=function(t){var e=u(t);!s(t)&&t.isDirty()&&(r.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),r.setItem(e+"time",(new Date).getTime().toString()),t.fire("StoreDraft"))},m=function(t){var e=u(t);c(t)&&(t.setContent(r.getItem(e+"draft"),{format:"raw"}),t.fire("RestoreDraft"))},v=function(t,e){var n=i(t.settings.autosave_interval,"30s");e.get()||(setInterval(function(){t.removed||l(t)},n),e.set(!0))},d=function(t){t.undoManager.transact(function(){m(t),f(t)}),t.focus()};function g(r){for(var o=[],t=1;t<arguments.length;t++)o[t-1]=arguments[t];return function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=o.concat(t);return r.apply(null,n)}}var y=tinymce.util.Tools.resolve("tinymce.EditorManager");y._beforeUnloadHandler=function(){var e;return o.each(y.get(),function(t){t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&t.getParam("autosave_ask_before_unload",!0)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))}),e};var p=function(n,r){return function(t){var e=t.control;e.disabled(!c(n)),n.on("StoreDraft RestoreDraft RemoveDraft",function(){e.disabled(!c(n))}),v(n,r)}};t.add("autosave",function(t){var e,n,r,o=a(!1);return window.onbeforeunload=y._beforeUnloadHandler,n=o,(e=t).addButton("restoredraft",{title:"Restore last draft",onclick:function(){d(e)},onPostRender:p(e,n)}),e.addMenuItem("restoredraft",{text:"Restore last draft",onclick:function(){d(e)},onPostRender:p(e,n),context:"file"}),t.on("init",function(){t.getParam("autosave_restore_when_empty",!1)&&t.dom.isEmpty(t.getBody())&&m(t)}),{hasDraft:g(c,r=t),storeDraft:g(l,r),restoreDraft:g(m,r),removeDraft:g(f,r),isEmpty:g(s,r)}})}();
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
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.
@@ -87,6 +87,7 @@
|
||||
<glyph unicode="" glyph-name="reload" d="M889.68 793.68c-93.608 102.216-228.154 166.32-377.68 166.32-282.77 0-512-229.23-512-512h96c0 229.75 186.25 416 416 416 123.020 0 233.542-53.418 309.696-138.306l-149.696-149.694h352v352l-134.32-134.32zM928 448c0-229.75-186.25-416-416-416-123.020 0-233.542 53.418-309.694 138.306l149.694 149.694h-352v-352l134.32 134.32c93.608-102.216 228.154-166.32 377.68-166.32 282.77 0 512 229.23 512 512h-96z" />
|
||||
<glyph unicode="" glyph-name="translate" d="M553.6 304l-118.4 118.4c80 89.6 137.6 195.2 172.8 304h137.6v92.8h-326.4v92.8h-92.8v-92.8h-326.4v-92.8h518.4c-32-89.6-80-176-147.2-249.6-44.8 48-80 99.2-108.8 156.8h-92.8c35.2-76.8 80-147.2 137.6-211.2l-236.8-233.6 67.2-67.2 233.6 233.6 144-144c3.2 0 38.4 92.8 38.4 92.8zM816 540.8h-92.8l-208-560h92.8l51.2 140.8h220.8l51.2-140.8h92.8l-208 560zM691.2 214.4l76.8 201.6 76.8-201.6h-153.6z" />
|
||||
<glyph unicode="" glyph-name="drag" d="M576 896h128v-128h-128v128zM576 640h128v-128h-128v128zM320 640h128v-128h-128v128zM576 384h128v-128h-128v128zM320 384h128v-128h-128v128zM320 128h128v-128h-128v128zM576 128h128v-128h-128v128zM320 896h128v-128h-128v128z" />
|
||||
<glyph unicode="" glyph-name="format-painter" d="M768 746.667v42.667c0 23.467-19.2 42.667-42.667 42.667h-512c-23.467 0-42.667-19.2-42.667-42.667v-170.667c0-23.467 19.2-42.667 42.667-42.667h512c23.467 0 42.667 19.2 42.667 42.667v42.667h42.667v-170.667h-426.667v-384c0-23.467 19.2-42.667 42.667-42.667h85.333c23.467 0 42.667 19.2 42.667 42.667v298.667h341.333v341.333h-128z" />
|
||||
<glyph unicode="" glyph-name="home" d="M1024 369.556l-512 397.426-512-397.428v162.038l512 397.426 512-397.428zM896 384v-384h-256v256h-256v-256h-256v384l384 288z" />
|
||||
<glyph unicode="" glyph-name="books" d="M576.234 670.73l242.712 81.432 203.584-606.784-242.712-81.432zM0 64h256v704h-256v-704zM64 640h128v-64h-128v64zM320 64h256v704h-256v-704zM384 640h128v-64h-128v64z" />
|
||||
<glyph unicode="" glyph-name="upload" d="M839.432 760.57c27.492-27.492 50.554-78.672 55.552-120.57h-318.984v318.984c41.898-4.998 93.076-28.060 120.568-55.552l142.864-142.862zM512 576v384h-368c-44 0-80-36-80-80v-864c0-44 36-80 80-80h672c44 0 80 36 80 80v560h-384zM576 192v-192h-192v192h-160l256 256 256-256h-160z" />
|
||||
|
||||
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
public/libs/tinymce/tinymce.min.js
vendored
4
public/libs/tinymce/tinymce.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -123,20 +123,21 @@ class PageDisplay {
|
||||
|
||||
setupStickySidebar() {
|
||||
// Make the sidebar stick in view on scroll
|
||||
let $window = $(window);
|
||||
let $sidebar = $("#sidebar .scroll-body");
|
||||
let $bookTreeParent = $sidebar.parent();
|
||||
const $window = $(window);
|
||||
const $sidebar = $("#sidebar .scroll-body");
|
||||
const $sidebarContainer = $sidebar.parent();
|
||||
const sidebarHeight = $sidebar.height() + 32;
|
||||
|
||||
// Check the page is scrollable and the content is taller than the tree
|
||||
let pageScrollable = ($(document).height() > ($window.height() + 40)) && ($sidebar.height() < $('.page-content').height());
|
||||
const pageScrollable = ($(document).height() > ($window.height() + 40)) && (sidebarHeight < $('.page-content').height());
|
||||
|
||||
// Get current tree's width and header height
|
||||
let headerHeight = $("#header").height() + $(".toolbar").height();
|
||||
const headerHeight = $("#header").height() + $(".toolbar").height();
|
||||
let isFixed = $window.scrollTop() > headerHeight;
|
||||
|
||||
// Fix the tree as a sidebar
|
||||
function stickTree() {
|
||||
$sidebar.width($bookTreeParent.width() + 15);
|
||||
$sidebar.width($sidebarContainer.width() + 15);
|
||||
$sidebar.addClass("fixed");
|
||||
isFixed = true;
|
||||
}
|
||||
|
||||
@@ -53,4 +53,9 @@
|
||||
// Fix to prevent 'No color' option from not being clickable.
|
||||
.mce-colorbtn-trans {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Fix to prevent CodeMirror focus events throwing TinyMCE cursor position.
|
||||
.mce-content-body .CodeMirrorContainer > .CodeMirror {
|
||||
pointer-events: none;
|
||||
}
|
||||
@@ -16,6 +16,14 @@ body {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.flex-fill {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.flex.sidebar + .flex.content {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.print-hidden {
|
||||
display: none;
|
||||
}
|
||||
@@ -31,4 +39,8 @@ h2 {
|
||||
line-height: 1;
|
||||
margin-top: 0.6em;
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
|
||||
.comments-container {
|
||||
display: none;
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Activity text strings.
|
||||
* Is used for all the text within activity logs & notifications.
|
||||
*/
|
||||
return [
|
||||
|
||||
/**
|
||||
* Activity text strings.
|
||||
* Is used for all the text within activity logs & notifications.
|
||||
*/
|
||||
|
||||
// Pages
|
||||
'page_create' => 'página creada',
|
||||
'page_create_notification' => 'Página creada exitosamente',
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* Authentication Language Lines
|
||||
* The following language lines are used during authentication for various
|
||||
* messages that we need to display to the user.
|
||||
*/
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used during authentication for various
|
||||
| messages that we need to display to the user. You are free to modify
|
||||
| these language lines according to your application's requirements.
|
||||
|
|
||||
*/
|
||||
|
||||
'failed' => 'Las credenciales no concuerdan con nuestros registros.',
|
||||
'throttle' => 'Demasiados intentos fallidos de conexión. Por favor intente nuevamente en :seconds segundos.',
|
||||
|
||||
/**
|
||||
* Login & Register
|
||||
*/
|
||||
// Login & Register
|
||||
'sign_up' => 'Registrarse',
|
||||
'log_in' => 'Acceder',
|
||||
'log_in_with' => 'Acceder con :socialDriver',
|
||||
@@ -43,23 +37,18 @@ return [
|
||||
'register_success' => '¡Gracias por registrarse! Ahora se encuentra registrado y logueado.',
|
||||
|
||||
|
||||
/**
|
||||
* Password Reset
|
||||
*/
|
||||
// Password Reset
|
||||
'reset_password' => 'Resetear Contraseña',
|
||||
'reset_password_send_instructions' => 'Introduzca su correo electrónico a continuación y le será enviado un correo con un link para la restauración',
|
||||
'reset_password_send_button' => 'Enviar Enlace de Reseteo',
|
||||
'reset_password_sent_success' => 'Un enlace para resetear la contraseña ha sido enviado a :email.',
|
||||
'reset_password_success' => 'Su password ha sido reseteado de manera éxitosa.',
|
||||
|
||||
'email_reset_subject' => 'Resetee la contraseña de :appName',
|
||||
'email_reset_text' => 'Está recibiendo este correo electrónico debido a que recibimos una solicitud de reseteo de contraseña de su cuenta.',
|
||||
'email_reset_not_requested' => 'Si no ha solicitado un reseteo de la contraseña, no es requerida ninguna acción por su parte.',
|
||||
|
||||
|
||||
/**
|
||||
* Email Confirmation
|
||||
*/
|
||||
// Email Confirmation
|
||||
'email_confirm_subject' => 'Confirme su correo electrónico en :appName',
|
||||
'email_confirm_greeting' => '¡Gracias por unirse a :appName!',
|
||||
'email_confirm_text' => 'Por favor confirme su dirección de correo electrónico haciendo click en el siguiente botón:',
|
||||
@@ -73,4 +62,4 @@ return [
|
||||
'email_not_confirmed_click_link' => 'Por favor siga el enlace en el correo electrónico que ha sido enviado durante el proceso de registro.',
|
||||
'email_not_confirmed_resend' => 'Si no puede encontrar el correo electrónico, puede solicitar el renvío del correo electrónico de confirmación rellenando el formulario que se muestra a continuación.',
|
||||
'email_not_confirmed_resend_button' => 'Reenviar Correo Electrónico de confirmación',
|
||||
];
|
||||
];
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* Common elements found throughout many areas of BookStack.
|
||||
*/
|
||||
return [
|
||||
|
||||
/**
|
||||
* Buttons
|
||||
*/
|
||||
// Buttons
|
||||
'cancel' => 'Cancelar',
|
||||
'confirm' => 'Confirmar',
|
||||
'back' => 'Atrás',
|
||||
@@ -12,18 +13,14 @@ return [
|
||||
'select' => 'Seleccionar',
|
||||
'more' => 'Más',
|
||||
|
||||
/**
|
||||
* Form Labels
|
||||
*/
|
||||
// Form Labels
|
||||
'name' => 'Nombre',
|
||||
'description' => 'Descripción',
|
||||
'role' => 'Rol',
|
||||
'cover_image' => 'Imagen de portada',
|
||||
'cover_image_description' => 'Esta imagen debe ser aproximadamente de 440x250px.',
|
||||
|
||||
/**
|
||||
* Actions
|
||||
*/
|
||||
// Actions
|
||||
'actions' => 'Acciones',
|
||||
'view' => 'Ver',
|
||||
'create' => 'Crear',
|
||||
@@ -40,9 +37,7 @@ return [
|
||||
'remove' => 'Remover',
|
||||
'add' => 'Añadir',
|
||||
|
||||
/**
|
||||
* Misc
|
||||
*/
|
||||
// Misc
|
||||
'deleted_user' => 'Usuario borrado',
|
||||
'no_activity' => 'Ninguna actividad para mostrar',
|
||||
'no_items' => 'No hay elementos disponibles',
|
||||
@@ -54,15 +49,11 @@ return [
|
||||
'list_view' => 'Vista en Lista',
|
||||
'default' => 'Predeterminada',
|
||||
|
||||
/**
|
||||
* Header
|
||||
*/
|
||||
// Header
|
||||
'view_profile' => 'Ver Perfil',
|
||||
'edit_profile' => 'Editar Perfil',
|
||||
|
||||
/**
|
||||
* Email Content
|
||||
*/
|
||||
// Email Content
|
||||
'email_action_help' => 'Si está teniendo problemas clicando en el botón ":actionText", copie y pegue la siguiente URL en su navegador web:',
|
||||
'email_rights' => 'Todos los derechos reservados',
|
||||
];
|
||||
];
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* Text used in custom JavaScript driven components.
|
||||
*/
|
||||
return [
|
||||
|
||||
/**
|
||||
* Image Manager
|
||||
*/
|
||||
// Image Manager
|
||||
'image_select' => 'Seleccionar Imagen',
|
||||
'image_all' => 'Todas',
|
||||
'image_all_title' => 'Ver todas las imágenes',
|
||||
@@ -24,9 +25,7 @@ return [
|
||||
'image_delete_success' => 'Imagen borrada exitosamente',
|
||||
'image_upload_remove' => 'Borrar',
|
||||
|
||||
/**
|
||||
* Code editor
|
||||
*/
|
||||
// Code Editor
|
||||
'code_editor' => 'Editar Código',
|
||||
'code_language' => 'Lenguaje del Código',
|
||||
'code_content' => 'Contenido del Código',
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* Text used for 'Entities' (Document Structure Elements) such as
|
||||
* Books, Shelves, Chapters & Pages
|
||||
*/
|
||||
return [
|
||||
|
||||
/**
|
||||
* Shared
|
||||
*/
|
||||
// Shared
|
||||
'recently_created' => 'Recientemente creado',
|
||||
'recently_created_pages' => 'Páginas recientemente creadas',
|
||||
'recently_updated_pages' => 'Páginas recientemente actualizadas',
|
||||
@@ -31,17 +33,13 @@ return [
|
||||
'export_pdf' => 'Archivo PDF',
|
||||
'export_text' => 'Archivo de texto',
|
||||
|
||||
/**
|
||||
* Permissions and restrictions
|
||||
*/
|
||||
// Permissions and restrictions
|
||||
'permissions' => 'Permisos',
|
||||
'permissions_intro' => 'Una vez habilitado, estos permisos tendrán prioridad por encima de cualquier permiso establecido.',
|
||||
'permissions_enable' => 'Habilitar permisos personalizados',
|
||||
'permissions_save' => 'Guardar permisos',
|
||||
|
||||
/**
|
||||
* Search
|
||||
*/
|
||||
// Search
|
||||
'search_results' => 'Resultados de búsqueda',
|
||||
'search_total_results_found' => 'Se han encontrado :count resultados|Se han encontrado :count resultados en total',
|
||||
'search_clear' => 'Limpiar resultados',
|
||||
@@ -66,9 +64,7 @@ return [
|
||||
'search_set_date' => 'fecha',
|
||||
'search_update' => 'Actualizar Búsqueda',
|
||||
|
||||
/**
|
||||
* Shelves
|
||||
*/
|
||||
// Shelves
|
||||
'shelf' => 'Estante',
|
||||
'shelves' => 'Estantes',
|
||||
'shelves_long' => 'Estantes',
|
||||
@@ -98,9 +94,7 @@ return [
|
||||
'shelves_copy_permissions_explain' => 'Esto aplicará los ajustes de permisos de este estante para todos sus libros. Antes de activarlo, asegúrese de que todos los cambios de permisos para este estante han sido guardados.',
|
||||
'shelves_copy_permission_success' => 'Permisos del estante copiados a :count libros',
|
||||
|
||||
/**
|
||||
* Books
|
||||
*/
|
||||
// Books
|
||||
'book' => 'Libro',
|
||||
'books' => 'Libros',
|
||||
'x_books' => ':count Libro|:count Libros',
|
||||
@@ -134,9 +128,7 @@ return [
|
||||
'books_sort_show_other' => 'Mostrar otros libros',
|
||||
'books_sort_save' => 'Guardar nuevo orden',
|
||||
|
||||
/**
|
||||
* Chapters
|
||||
*/
|
||||
// Chapters
|
||||
'chapter' => 'Capítulo',
|
||||
'chapters' => 'Capítulos',
|
||||
'x_chapters' => ':count Capítulo|:count Capítulos',
|
||||
@@ -159,9 +151,7 @@ return [
|
||||
'chapters_permissions_success' => 'Permisos de capítulo actualizados',
|
||||
'chapters_search_this' => 'Buscar este capítulo',
|
||||
|
||||
/**
|
||||
* Pages
|
||||
*/
|
||||
// Pages
|
||||
'page' => 'Página',
|
||||
'pages' => 'Páginas',
|
||||
'x_pages' => ':count Página|:count Páginas',
|
||||
@@ -235,9 +225,7 @@ return [
|
||||
'pages_draft_discarded' => 'Borrador descartado, el editor ha sido actualizado con el contenido de la página actual',
|
||||
'pages_specific' => 'Página específica',
|
||||
|
||||
/**
|
||||
* Editor sidebar
|
||||
*/
|
||||
// Editor Sidebar
|
||||
'page_tags' => 'Etiquetas de Página',
|
||||
'chapter_tags' => 'Etiquetas de Capítulo',
|
||||
'book_tags' => 'Etiquetas de Libro',
|
||||
@@ -273,18 +261,14 @@ return [
|
||||
'attachments_file_updated' => 'Fichero actualizado éxitosamente',
|
||||
'attachments_link_attached' => 'Enlace agregado éxitosamente a la ágina',
|
||||
|
||||
/**
|
||||
* Profile View
|
||||
*/
|
||||
// Profile View
|
||||
'profile_user_for_x' => 'Usuario para :time',
|
||||
'profile_created_content' => 'Contenido creado',
|
||||
'profile_not_created_pages' => ':userName no ha creado ninguna página',
|
||||
'profile_not_created_chapters' => ':userName no ha creado ningún capítulo',
|
||||
'profile_not_created_books' => ':userName no ha creado ningún libro',
|
||||
|
||||
/**
|
||||
* Comments
|
||||
*/
|
||||
// Comments
|
||||
'comment' => 'Comentario',
|
||||
'comments' => 'Comentarios',
|
||||
'comment_add' => 'Añadir Comentario',
|
||||
@@ -302,10 +286,8 @@ return [
|
||||
'comment_delete_confirm' => '¿Está seguro de que quiere borrar este comentario?',
|
||||
'comment_in_reply_to' => 'En respuesta a :commentId',
|
||||
|
||||
/**
|
||||
* Revision
|
||||
*/
|
||||
// Revision
|
||||
'revision_delete_confirm' => '¿Está seguro de que desea eliminar esta revisión?',
|
||||
'revision_delete_success' => 'Revisión eliminada',
|
||||
'revision_cannot_delete_latest' => 'No se puede eliminar la última revisión.'
|
||||
];
|
||||
];
|
||||
@@ -1,11 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Text shown in error messaging.
|
||||
*/
|
||||
return [
|
||||
|
||||
/**
|
||||
* Error text strings.
|
||||
*/
|
||||
|
||||
// Permissions
|
||||
'permission' => 'No tiene permisos para visualizar la página solicitada.',
|
||||
'permissionJson' => 'No tiene permisos para ejecutar la acción solicitada.',
|
||||
@@ -81,4 +79,5 @@ return [
|
||||
'error_occurred' => 'Ha ocurrido un error',
|
||||
'app_down' => 'La aplicación :appName se encuentra caída en este momento',
|
||||
'back_soon' => 'Volverá a estar operativa pronto.',
|
||||
|
||||
];
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Pagination Language Lines
|
||||
* The following language lines are used by the paginator library to build
|
||||
* the simple pagination links.
|
||||
*/
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Pagination Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used by the paginator library to build
|
||||
| the simple pagination links. You are free to change them to anything
|
||||
| you want to customize your views to better match your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'previous' => '« Anterior',
|
||||
'next' => 'Siguiente »',
|
||||
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Password Reminder Language Lines
|
||||
* The following language lines are the default lines which match reasons
|
||||
* that are given by the password broker for a password update attempt has failed.
|
||||
*/
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reminder Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are the default lines which match reasons
|
||||
| that are given by the password broker for a password update attempt
|
||||
| has failed, such as for an invalid token or invalid new password.
|
||||
|
|
||||
*/
|
||||
|
||||
'password' => 'La contraseña debe ser como mínimo de seis caracteres y coincidir con la confirmación.',
|
||||
'user' => "No podemos encontrar un usuario con esta dirección de correo electrónico.",
|
||||
'token' => 'El token de reseteo de la contraseña es inválido.',
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Settings text strings
|
||||
* Contains all text strings used in the general settings sections of BookStack
|
||||
* including users and roles.
|
||||
*/
|
||||
return [
|
||||
|
||||
/**
|
||||
* Settings text strings
|
||||
* Contains all text strings used in the general settings sections of BookStack
|
||||
* including users and roles.
|
||||
*/
|
||||
|
||||
// Common Messages
|
||||
'settings' => 'Ajustes',
|
||||
'settings_save' => 'Guardar ajustes',
|
||||
'settings_save_success' => 'Ajustes guardados',
|
||||
|
||||
/**
|
||||
* App settings
|
||||
*/
|
||||
|
||||
// App Settings
|
||||
'app_settings' => 'Ajustes de la aplicación',
|
||||
'app_name' => 'Nombre de la aplicación',
|
||||
'app_name_desc' => 'Este nombre se muestra en la cabecera y en cualquier correo electrónico',
|
||||
@@ -37,10 +33,7 @@ return [
|
||||
'app_disable_comments' => 'Deshabilitar comentarios',
|
||||
'app_disable_comments_desc' => 'Deshabilita los comentarios en todas las páginas de la aplicación. Los comentarios existentes no se muestran.',
|
||||
|
||||
/**
|
||||
* Registration settings
|
||||
*/
|
||||
|
||||
// Registration Settings
|
||||
'reg_settings' => 'Ajustes de registro',
|
||||
'reg_allow' => '¿Permitir registro?',
|
||||
'reg_default_role' => 'Rol de usuario por defecto después del registro',
|
||||
@@ -50,10 +43,7 @@ return [
|
||||
'reg_confirm_restrict_domain_desc' => 'Introduzca una lista separada por comas de los dominio a los que les gustaría restringir el registro de usuarios. A los usuarios les será enviado un correo electrónico para confirmar la dirección antes de que se le permita interactuar con la aplicación. <br> Tenga en cuenta que los usuarios podrán cambiar sus direcciones de correo electrónico después de registrarse exitosamente.',
|
||||
'reg_confirm_restrict_domain_placeholder' => 'Ninguna restricción establecida',
|
||||
|
||||
/**
|
||||
* Maintenance settings
|
||||
*/
|
||||
|
||||
// Maintenance settings
|
||||
'maint' => 'Mantenimiento',
|
||||
'maint_image_cleanup' => 'Limpiar imágenes',
|
||||
'maint_image_cleanup_desc' => "Analiza las páginas y sus revisiones para comprobar qué imágenes y dibujos están siendo utilizadas y cuales no son necesarias. Asegúrate de crear una copia completa de la base de datos y de las imágenes antes de lanzar esta opción.",
|
||||
@@ -63,10 +53,7 @@ return [
|
||||
'maint_image_cleanup_success' => '¡Se han encontrado y borrado :count imágenes posiblemente no utilizadas!',
|
||||
'maint_image_cleanup_nothing_found' => '¡No se han encontrado imágenes sin utilizar, no se han borrado imágenes!',
|
||||
|
||||
/**
|
||||
* Role settings
|
||||
*/
|
||||
|
||||
// Role Settings
|
||||
'roles' => 'Roles',
|
||||
'role_user_roles' => 'Roles de usuario',
|
||||
'role_create' => 'Crear nuevo rol',
|
||||
@@ -99,10 +86,7 @@ return [
|
||||
'role_users' => 'Usuarios en este rol',
|
||||
'role_users_none' => 'No hay usuarios asignados a este rol',
|
||||
|
||||
/**
|
||||
* Users
|
||||
*/
|
||||
|
||||
// Users
|
||||
'users' => 'Usuarios',
|
||||
'user_profile' => 'Perfil de usuario',
|
||||
'users_add_new' => 'Agregar nuevo usuario',
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validation Lines
|
||||
* The following language lines contain the default error messages used by
|
||||
* the validator class. Some of these rules have multiple versions such
|
||||
* as the size rules. Feel free to tweak each of these messages here.
|
||||
*/
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines contain the default error messages used by
|
||||
| the validator class. Some of these rules have multiple versions such
|
||||
| as the size rules. Feel free to tweak each of these messages here.
|
||||
|
|
||||
*/
|
||||
|
||||
// Standard laravel validation lines
|
||||
'accepted' => 'El :attribute debe ser aceptado.',
|
||||
'active_url' => 'El :attribute no es una URL válida.',
|
||||
'after' => 'El :attribute debe ser una fecha posterior :date.',
|
||||
@@ -75,34 +70,13 @@ return [
|
||||
'unique' => 'El atributo :attribute ya ha sido tomado.',
|
||||
'url' => 'El atributo :attribute tiene un formato inválido.',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify custom validation messages for attributes using the
|
||||
| convention "attribute.rule" to name the lines. This makes it quick to
|
||||
| specify a specific custom language line for a given attribute rule.
|
||||
|
|
||||
*/
|
||||
|
||||
// Custom validation lines
|
||||
'custom' => [
|
||||
'password-confirm' => [
|
||||
'required_with' => 'Requerida confirmación de contraseña',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Attributes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used to swap attribute place-holders
|
||||
| with something more reader friendly such as E-Mail Address instead
|
||||
| of "email". This simply helps us make messages a little cleaner.
|
||||
|
|
||||
*/
|
||||
|
||||
// Custom validation attributes
|
||||
'attributes' => [],
|
||||
|
||||
];
|
||||
|
||||
@@ -55,7 +55,13 @@
|
||||
@if(signedInUser() && userCan('settings-manage'))
|
||||
<a href="{{ baseUrl('/settings') }}">@icon('settings'){{ trans('settings.settings') }}</a>
|
||||
@endif
|
||||
@if(signedInUser() && userCan('users-manage') && !userCan('settings-manage'))
|
||||
<a href="{{ baseUrl('/settings/users') }}">@icon('users'){{ trans('settings.users') }}</a>
|
||||
@endif
|
||||
@if(!signedInUser())
|
||||
@if(setting('registration-enabled', false))
|
||||
<a href="{{ baseUrl("/register") }}">@icon('new-user') {{ trans('auth.sign_up') }}</a>
|
||||
@endif
|
||||
<a href="{{ baseUrl('/login') }}">@icon('login') {{ trans('auth.log_in') }}</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
@if(userCan('chapter-update', $chapter))
|
||||
<a href="{{ $chapter->getUrl('/edit') }}" class="text-primary text-button">@icon('edit'){{ trans('common.edit') }}</a>
|
||||
@endif
|
||||
@if(userCan('chapter-update', $chapter) || userCan('restrictions-manage', $chapter) || userCan('chapter-delete', $chapter))
|
||||
@if((userCan('chapter-update', $chapter) && userCan('chapter-delete', $chapter) )|| userCan('restrictions-manage', $chapter) || userCan('chapter-delete', $chapter))
|
||||
<div dropdown class="dropdown-container">
|
||||
<a dropdown-toggle class="text-primary text-button">@icon('more') {{ trans('common.more') }}</a>
|
||||
<ul>
|
||||
@if(userCan('chapter-update', $chapter))
|
||||
@if(userCan('chapter-update', $chapter) && userCan('chapter-delete', $chapter))
|
||||
<li><a href="{{ $chapter->getUrl('/move') }}" class="text-primary">@icon('folder'){{ trans('common.move') }}</a></li>
|
||||
@endif
|
||||
@if(userCan('restrictions-manage', $chapter))
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
@endif
|
||||
</td>
|
||||
<td> @if($revision->createdBy) {{ $revision->createdBy->name }} @else {{ trans('common.deleted_user') }} @endif</td>
|
||||
<td><small>{{ $revision->created_at->format('jS F, Y H:i:s') }} <br> ({{ $revision->created_at->diffForHumans() }})</small></td>
|
||||
<td><small>{{ $revision->created_at->formatLocalized('%e %B %Y %H:%M:%S') }} <br> ({{ $revision->created_at->diffForHumans() }})</small></td>
|
||||
<td>{{ $revision->summary }}</td>
|
||||
<td class="actions">
|
||||
<a href="{{ $revision->getUrl('changes') }}" target="_blank">{{ trans('entities.pages_revisions_changes') }}</a>
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
<ul>
|
||||
@if(userCan('page-update', $page))
|
||||
<li><a href="{{ $page->getUrl('/copy') }}" class="text-primary" >@icon('copy'){{ trans('common.copy') }}</a></li>
|
||||
<li><a href="{{ $page->getUrl('/move') }}" class="text-primary" >@icon('folder'){{ trans('common.move') }}</a></li>
|
||||
@if(userCan('page-delete', $page))
|
||||
<li><a href="{{ $page->getUrl('/move') }}" class="text-primary" >@icon('folder'){{ trans('common.move') }}</a></li>
|
||||
@endif
|
||||
<li><a href="{{ $page->getUrl('/revisions') }}" class="text-primary">@icon('history'){{ trans('entities.revisions') }}</a></li>
|
||||
@endif
|
||||
@if(userCan('restrictions-manage', $page))
|
||||
|
||||
@@ -37,22 +37,27 @@
|
||||
</div>
|
||||
<div class="col-md-5 text-bigger" id="content-counts">
|
||||
<div class="text-muted">{{ trans('entities.profile_created_content') }}</div>
|
||||
<div class="text-book">
|
||||
@icon('book') {{ trans_choice('entities.x_books', $assetCounts['books']) }}
|
||||
</div>
|
||||
<div class="text-chapter">
|
||||
@icon('chapter') {{ trans_choice('entities.x_chapters', $assetCounts['chapters']) }}
|
||||
</div>
|
||||
<div class="text-page">
|
||||
@icon('page') {{ trans_choice('entities.x_pages', $assetCounts['pages']) }}
|
||||
</div>
|
||||
<a href="#recent-books">
|
||||
<div class="text-book">
|
||||
@icon('book') {{ trans_choice('entities.x_books', $assetCounts['books']) }}
|
||||
</div>
|
||||
</a>
|
||||
<a href="#recent-chapters">
|
||||
<div class="text-chapter">
|
||||
@icon('chapter') {{ trans_choice('entities.x_chapters', $assetCounts['chapters']) }}
|
||||
</div>
|
||||
</a>
|
||||
<a href="#recent-pages">
|
||||
<div class="text-page">
|
||||
@icon('page') {{ trans_choice('entities.x_pages', $assetCounts['pages']) }}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<hr class="even">
|
||||
|
||||
<h3>{{ trans('entities.recently_created_pages') }}</h3>
|
||||
<h3 id="recent-pages">{{ trans('entities.recently_created_pages') }}</h3>
|
||||
@if (count($recentlyCreated['pages']) > 0)
|
||||
@include('partials/entity-list', ['entities' => $recentlyCreated['pages']])
|
||||
@else
|
||||
@@ -60,8 +65,7 @@
|
||||
@endif
|
||||
|
||||
<hr class="even">
|
||||
|
||||
<h3>{{ trans('entities.recently_created_chapters') }}</h3>
|
||||
<h3 id="recent-chapters">{{ trans('entities.recently_created_chapters') }}</h3>
|
||||
@if (count($recentlyCreated['chapters']) > 0)
|
||||
@include('partials/entity-list', ['entities' => $recentlyCreated['chapters']])
|
||||
@else
|
||||
@@ -69,8 +73,7 @@
|
||||
@endif
|
||||
|
||||
<hr class="even">
|
||||
|
||||
<h3>{{ trans('entities.recently_created_books') }}</h3>
|
||||
<h3 id="recent-books">{{ trans('entities.recently_created_books') }}</h3>
|
||||
@if (count($recentlyCreated['books']) > 0)
|
||||
@include('partials/entity-list', ['entities' => $recentlyCreated['books']])
|
||||
@else
|
||||
|
||||
@@ -40,15 +40,18 @@ class PageContentTest extends TestCase
|
||||
{
|
||||
$page = Page::first();
|
||||
$secondPage = Page::where('id', '!=', $page->id)->first();
|
||||
|
||||
$this->asEditor();
|
||||
$page->html = "<p>{{@$secondPage->id}}</p>";
|
||||
$includeTag = '{{@' . $secondPage->id . '}}';
|
||||
$page->html = '<p>' . $includeTag . '</p>';
|
||||
|
||||
$resp = $this->put($page->getUrl(), ['name' => $page->name, 'html' => $page->html, 'summary' => '']);
|
||||
|
||||
$resp->assertStatus(302);
|
||||
|
||||
$page = Page::find($page->id);
|
||||
$this->assertContains("{{@$secondPage->id}}", $page->html);
|
||||
$this->assertContains($includeTag, $page->html);
|
||||
$this->assertEquals('', $page->text);
|
||||
}
|
||||
|
||||
public function test_page_includes_do_not_break_tables()
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
use BookStack\Entities\Book;
|
||||
use BookStack\Entities\Chapter;
|
||||
use BookStack\Entities\Page;
|
||||
use BookStack\Entities\Repos\EntityRepo;
|
||||
use BookStack\Entities\Repos\PageRepo;
|
||||
|
||||
class SortTest extends TestCase
|
||||
@@ -58,14 +57,14 @@ class SortTest extends TestCase
|
||||
$newBook = Book::where('id', '!=', $currentBook->id)->first();
|
||||
$editor = $this->getEditor();
|
||||
|
||||
$this->setEntityRestrictions($newBook, ['view', 'edit', 'delete'], $editor->roles);
|
||||
$this->setEntityRestrictions($newBook, ['view', 'update', 'delete'], $editor->roles);
|
||||
|
||||
$movePageResp = $this->actingAs($editor)->put($page->getUrl('/move'), [
|
||||
'entity_selection' => 'book:' . $newBook->id
|
||||
]);
|
||||
$this->assertPermissionError($movePageResp);
|
||||
|
||||
$this->setEntityRestrictions($newBook, ['view', 'edit', 'delete', 'create'], $editor->roles);
|
||||
$this->setEntityRestrictions($newBook, ['view', 'update', 'delete', 'create'], $editor->roles);
|
||||
$movePageResp = $this->put($page->getUrl('/move'), [
|
||||
'entity_selection' => 'book:' . $newBook->id
|
||||
]);
|
||||
@@ -76,6 +75,33 @@ class SortTest extends TestCase
|
||||
$this->assertTrue($page->book->id == $newBook->id, 'Page book is now the new book');
|
||||
}
|
||||
|
||||
public function test_page_move_requires_delete_permissions()
|
||||
{
|
||||
$page = Page::first();
|
||||
$currentBook = $page->book;
|
||||
$newBook = Book::where('id', '!=', $currentBook->id)->first();
|
||||
$editor = $this->getEditor();
|
||||
|
||||
$this->setEntityRestrictions($newBook, ['view', 'update', 'create', 'delete'], $editor->roles);
|
||||
$this->setEntityRestrictions($page, ['view', 'update', 'create'], $editor->roles);
|
||||
|
||||
$movePageResp = $this->actingAs($editor)->put($page->getUrl('/move'), [
|
||||
'entity_selection' => 'book:' . $newBook->id
|
||||
]);
|
||||
$this->assertPermissionError($movePageResp);
|
||||
$pageView = $this->get($page->getUrl());
|
||||
$pageView->assertDontSee($page->getUrl('/move'));
|
||||
|
||||
$this->setEntityRestrictions($page, ['view', 'update', 'create', 'delete'], $editor->roles);
|
||||
$movePageResp = $this->put($page->getUrl('/move'), [
|
||||
'entity_selection' => 'book:' . $newBook->id
|
||||
]);
|
||||
|
||||
$page = Page::find($page->id);
|
||||
$movePageResp->assertRedirect($page->getUrl());
|
||||
$this->assertTrue($page->book->id == $newBook->id, 'Page book is now the new book');
|
||||
}
|
||||
|
||||
public function test_chapter_move()
|
||||
{
|
||||
$chapter = Chapter::first();
|
||||
@@ -104,6 +130,33 @@ class SortTest extends TestCase
|
||||
$pageCheckResp->assertSee($newBook->name);
|
||||
}
|
||||
|
||||
public function test_chapter_move_requires_delete_permissions()
|
||||
{
|
||||
$chapter = Chapter::first();
|
||||
$currentBook = $chapter->book;
|
||||
$newBook = Book::where('id', '!=', $currentBook->id)->first();
|
||||
$editor = $this->getEditor();
|
||||
|
||||
$this->setEntityRestrictions($newBook, ['view', 'update', 'create', 'delete'], $editor->roles);
|
||||
$this->setEntityRestrictions($chapter, ['view', 'update', 'create'], $editor->roles);
|
||||
|
||||
$moveChapterResp = $this->actingAs($editor)->put($chapter->getUrl('/move'), [
|
||||
'entity_selection' => 'book:' . $newBook->id
|
||||
]);
|
||||
$this->assertPermissionError($moveChapterResp);
|
||||
$pageView = $this->get($chapter->getUrl());
|
||||
$pageView->assertDontSee($chapter->getUrl('/move'));
|
||||
|
||||
$this->setEntityRestrictions($chapter, ['view', 'update', 'create', 'delete'], $editor->roles);
|
||||
$moveChapterResp = $this->put($chapter->getUrl('/move'), [
|
||||
'entity_selection' => 'book:' . $newBook->id
|
||||
]);
|
||||
|
||||
$chapter = Chapter::find($chapter->id);
|
||||
$moveChapterResp->assertRedirect($chapter->getUrl());
|
||||
$this->assertTrue($chapter->book->id == $newBook->id, 'Page book is now the new book');
|
||||
}
|
||||
|
||||
public function test_book_sort()
|
||||
{
|
||||
$oldBook = Book::query()->first();
|
||||
|
||||
@@ -109,6 +109,16 @@ class RolesTest extends BrowserKitTest
|
||||
->seePageIs('/settings/users');
|
||||
}
|
||||
|
||||
public function test_manage_users_permission_shows_link_in_header_if_does_not_have_settings_manage_permision()
|
||||
{
|
||||
$usersLink = 'href="'.url('/settings/users') . '"';
|
||||
$this->actingAs($this->user)->visit('/')->dontSee($usersLink);
|
||||
$this->giveUserPermissions($this->user, ['users-manage']);
|
||||
$this->actingAs($this->user)->visit('/')->see($usersLink);
|
||||
$this->giveUserPermissions($this->user, ['settings-manage', 'users-manage']);
|
||||
$this->actingAs($this->user)->visit('/')->dontSee($usersLink);
|
||||
}
|
||||
|
||||
public function test_user_roles_manage_permission()
|
||||
{
|
||||
$this->actingAs($this->user)->visit('/settings/roles')
|
||||
|
||||
@@ -14,6 +14,24 @@ class PublicActionTest extends BrowserKitTest
|
||||
$this->visit($page->getUrl())->seePageIs('/login');
|
||||
}
|
||||
|
||||
public function test_login_link_visible()
|
||||
{
|
||||
$this->setSettings(['app-public' => 'true']);
|
||||
$this->visit('/')->see(url('/login'));
|
||||
}
|
||||
|
||||
public function test_register_link_visible_when_enabled()
|
||||
{
|
||||
$this->setSettings(['app-public' => 'true']);
|
||||
|
||||
$this->visit('/')->see(url('/login'));
|
||||
$this->visit('/')->dontSee(url('/register'));
|
||||
|
||||
$this->setSettings(['app-public' => 'true', 'registration-enabled' => 'true']);
|
||||
$this->visit('/')->see(url('/login'));
|
||||
$this->visit('/')->see(url('/register'));
|
||||
}
|
||||
|
||||
public function test_books_viewable()
|
||||
{
|
||||
$this->setSettings(['app-public' => 'true']);
|
||||
|
||||
Reference in New Issue
Block a user