Fix/update wysiwyg styles (#8844)

This is a refactoring of the CSS classes in the WYSIWYG editor. The classes now use proper BEM and are almost completely independent of other CSS. It also includes small style refactorings, like a reduction of heading size in attribute fields, and an increase in heading size in all other instances.

* Initial class definitions

* Added more classes

* Added Table of Contents basics

* CkEditor applying custom CSS classes to p, h1, h2, h3, h4, h5, h6, li and blockquote

* CKEditorInspector removed

* op css class for headings

* op css class for paragraphs

* op css class for code/code block

* adapt specs to altered markdown/html generation

* adapt grid/budget representers to altered signature

* op css class for lists

* op css class for toc

* op css class for links

* Start working on typography css

* op css class for tables

* Fixing more typography, trying out larger headers

* Applying custom classes to li, a, blockquote, figure, table, tr, td, th, image, codeblock, figcaption and macros

* adapt specs to altered link classes

* op css class for images

* apply user content container class throughout application

* CSS alignment custom classes applied to table

* op css class for task list checkbox

* Added task checkbox class

* amend list checkbox class in backend

* op css class for table thead element

* adapt specs on image html generation

* Updated table and typography styles

* Update typography and figure styles

* Figure overflow handling

* Table alignment styles + ckEditor styles removed

* rename wiki-anchor to op-uc-link_permalink

* wrap table in div as well as figure

* Updated code-block

* Update permalinks

* Fixed a lot about tables

* Removed Description header from work-packages page

* Fix frontend styles

* Add placeholder styling, fix toc

* Fixed figure print

* working with table aligns

* Custom class add to task lists

* Custom classes applied to theads

* op-uc-container custom class added to container

* Codeblocks inside pre elements

* Fix: single <code> and <a> tags

* explicitly require overwritten gem class

Apparently, the gem is not loaded yet when it is registered as a filter when in eager loading mode

* adapt spec expectation to altered toc rendering

* CkInspector removed

* Latest ckeditor changes

* remove highlight css class from wiki content

* allow html pipleline to handle macros with additional classes

* Fixed a lot of print css for tables

* Add general print css back in

* Update Table of Contents styling

* Custom classes on ul, ol, li and task-lists

* Revert "Custom classes on ul, ol, li and task-lists"

This reverts commit 0d27d28137.

* Custom classes on ul, ol, li and task-lists

* Custom classes on column's th

* remove placeholder class when rendering

* WOrking on task lists

* Changing task-list classes, changed tests

* Updated list styles

* Remove unused todo list styles

* remove checked in binstubs

* Fix table of contents

* adapt todo list handing in backend pipeline

* adapt specs to altered css classes

* Add numbers to table of contents

* Better comments in table of contents

* Fix: wrap single <table> with a <figure>

* Fixes to todo list design

* Updated todo list scss to fix nested lists

* adapt selectors in table spec

* Update table styles

* Improve table borders more

* Custom classes specs

* Fix: no need to remove regular list classes when its type changes

* Add modifier for inline headings

* Update table editing styles

* Remove break-word tests

* wrap images just like tables

* Update figure content styles

* Fix: All tests passing (ul.op-uc-list_task-list)

* div.op-uc-figure--content wrapping tables

* Specs for figures wrappers div.op-uc-figure--content

* Fix: add custom classes to links and codes again

* Table wrapper div reverted + specs

* Fix inline palceholders

* Custom macro type classes

* Add basic macro placeholder changes

* Move heading permalink after text

* Fix word-break spec

* Sending figure styles to the backend (width)

* extend test to take ckeditor placeholder into account

* avoid adding bem classes multiple times

* attempt to fix flickering spec

* Removing image spinner when uploading finishes

* adapt spec expectations

Co-authored-by: Aleix Suau <info@macrofonoestudio.es>
Co-authored-by: ulferts <jens.ulferts@googlemail.com>
pull/8867/head
Benjamin Bädorf 4 years ago committed by GitHub
parent 8688e3a34d
commit e848d44dea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/services/api/v3/work_package_collection_from_query_service.rb
  2. 2
      app/views/announcements/_show.html.erb
  3. 4
      app/views/homescreen/blocks/_header.html.erb
  4. 2
      app/views/homescreen/blocks/_welcome.html.erb
  5. 4
      app/views/layouts/base.html.erb
  6. 2
      app/views/layouts/project_mailer.html.erb
  7. 1
      app/views/layouts/styleguide/styleguide.layout.html.erb
  8. 2
      app/views/layouts/user_mailer.html.erb
  9. 4
      app/views/messages/show.html.erb
  10. 2
      app/views/news/index.html.erb
  11. 4
      app/views/versions/_overview.html.erb
  12. 2
      app/views/wiki/_content.html.erb
  13. 6
      app/views/wiki/export_multiple.html.erb
  14. 6
      frontend/src/app/components/work-packages/wp-single-view/wp-single-view.html
  15. 2
      frontend/src/app/components/wp-activity/user/user-activity.component.html
  16. 3
      frontend/src/app/modules/boards/index-page/boards-index-page.component.html
  17. 2
      frontend/src/app/modules/common/editable-toolbar-title/editable-toolbar-title.html
  18. 8
      frontend/src/app/modules/fields/display/field-types/formattable-display-field.module.ts
  19. 2
      frontend/src/app/modules/fields/help-texts/help-text.modal.html
  20. 8
      frontend/src/app/modules/grids/widgets/custom-text/custom-text.component.html
  21. 2
      frontend/src/app/modules/grids/widgets/documents/documents.component.html
  22. 5
      frontend/src/global_styles/content/_blockquotes.sass
  23. 6
      frontend/src/global_styles/content/_help_texts.sass
  24. 2
      frontend/src/global_styles/content/_index.sass
  25. 2
      frontend/src/global_styles/content/_table.sass
  26. 8
      frontend/src/global_styles/content/_wiki.lsg
  27. 186
      frontend/src/global_styles/content/_wiki.sass
  28. 23
      frontend/src/global_styles/content/editor/_ckeditor.sass
  29. 1
      frontend/src/global_styles/content/editor/_index.sass
  30. 18
      frontend/src/global_styles/content/editor/_macros.sass
  31. 58
      frontend/src/global_styles/content/editor/_markdown.sass
  32. 2
      frontend/src/global_styles/content/editor/_rouge.scss
  33. 45
      frontend/src/global_styles/content/user-content/_figure.sass
  34. 3
      frontend/src/global_styles/content/user-content/_image.sass
  35. 30
      frontend/src/global_styles/content/user-content/_index.sass
  36. 27
      frontend/src/global_styles/content/user-content/_list.sass
  37. 3
      frontend/src/global_styles/content/user-content/_macros.sass
  38. 16
      frontend/src/global_styles/content/user-content/_mixins.sass
  39. 7
      frontend/src/global_styles/content/user-content/_placeholder.sass
  40. 36
      frontend/src/global_styles/content/user-content/_table.sass
  41. 26
      frontend/src/global_styles/content/user-content/_toc.sass
  42. 85
      frontend/src/global_styles/content/user-content/_typography.sass
  43. 3
      frontend/src/global_styles/content/user-content/_user-content.lsg
  44. 5
      frontend/src/global_styles/content/work_packages/_table_content.sass
  45. 2
      frontend/src/global_styles/layout/_print.sass
  46. 6
      frontend/src/global_styles/layout/_toolbar.sass
  47. 3
      frontend/src/global_styles/layout/work_packages/_details_view.sass
  48. 2
      frontend/src/global_styles/layout/work_packages/_full_view.sass
  49. 6
      frontend/src/global_styles/layout/work_packages/_table_embedded.sass
  50. 733
      frontend/src/vendor/ckeditor/ckeditor.js
  51. 2
      frontend/src/vendor/ckeditor/ckeditor.js.map
  52. 2
      lib/api/decorators/collection.rb
  53. 4
      lib/api/decorators/offset_paginated_collection.rb
  54. 6
      lib/api/decorators/schema_representer.rb
  55. 4
      lib/api/decorators/unpaginated_collection.rb
  56. 2
      lib/api/v3/activities/activities_by_work_package_api.rb
  57. 2
      lib/api/v3/attachments/attachable_representer_mixin.rb
  58. 2
      lib/api/v3/attachments/attachments_by_container_api.rb
  59. 3
      lib/api/v3/categories/categories_by_project_api.rb
  60. 2
      lib/api/v3/help_texts/help_texts_api.rb
  61. 4
      lib/api/v3/memberships/schemas/membership_schema_representer.rb
  62. 2
      lib/api/v3/news/news_api.rb
  63. 2
      lib/api/v3/principals/principals_api.rb
  64. 2
      lib/api/v3/priorities/priorities_api.rb
  65. 2
      lib/api/v3/projects/available_assignees_api.rb
  66. 2
      lib/api/v3/projects/available_responsibles_api.rb
  67. 2
      lib/api/v3/projects/project_collection_representer.rb
  68. 2
      lib/api/v3/queries/queries_api.rb
  69. 4
      lib/api/v3/queries/query_collection_representer.rb
  70. 4
      lib/api/v3/queries/schemas/query_filter_instance_schema_api.rb
  71. 2
      lib/api/v3/queries/schemas/query_project_filter_instance_schema_api.rb
  72. 2
      lib/api/v3/queries/schemas/query_project_schema_api.rb
  73. 2
      lib/api/v3/queries/schemas/query_schema_api.rb
  74. 6
      lib/api/v3/queries/schemas/query_schema_representer.rb
  75. 2
      lib/api/v3/repositories/revisions_by_work_package_api.rb
  76. 6
      lib/api/v3/schemas/schema_collection_representer.rb
  77. 2
      lib/api/v3/statuses/statuses_api.rb
  78. 5
      lib/api/v3/types/types_api.rb
  79. 2
      lib/api/v3/types/types_by_project_api.rb
  80. 2
      lib/api/v3/users/users_api.rb
  81. 6
      lib/api/v3/utilities/custom_field_injector.rb
  82. 4
      lib/api/v3/utilities/endpoints/index.rb
  83. 2
      lib/api/v3/utilities/endpoints/schema.rb
  84. 2
      lib/api/v3/utilities/params_to_query.rb
  85. 5
      lib/api/v3/versions/projects_by_version_api.rb
  86. 4
      lib/api/v3/versions/schemas/version_schema_representer.rb
  87. 2
      lib/api/v3/work_packages/available_projects_on_create_api.rb
  88. 2
      lib/api/v3/work_packages/available_projects_on_edit_api.rb
  89. 2
      lib/api/v3/work_packages/form_representer.rb
  90. 4
      lib/api/v3/work_packages/schema/work_package_schema_representer.rb
  91. 4
      lib/api/v3/work_packages/schema/work_package_schemas_api.rb
  92. 4
      lib/api/v3/work_packages/watchers_api.rb
  93. 6
      lib/api/v3/work_packages/work_package_collection_representer.rb
  94. 2
      lib/api/v3/work_packages/work_package_relations_api.rb
  95. 2
      lib/api/v3/work_packages/work_package_representer.rb
  96. 4
      lib/open_project/text_formatting/filters/autolink_filter.rb
  97. 94
      lib/open_project/text_formatting/filters/bem_css_filter.rb
  98. 87
      lib/open_project/text_formatting/filters/figure_wrapped_filter.rb
  99. 8
      lib/open_project/text_formatting/filters/macro_filter.rb
  100. 4
      lib/open_project/text_formatting/filters/macros/embedded_table.rb
  101. Some files were not shown because too many files have changed in this diff Show More

@ -145,7 +145,7 @@ module API
::API::V3::WorkPackages::WorkPackageCollectionRepresenter.new(
work_packages,
self_link(project),
self_link: self_link(project),
project: project,
query: resulting_params,
page: resulting_params[:offset],

@ -2,7 +2,7 @@
<% if announcement.present? %>
<div id="announcement">
<div class="notification-box -info">
<div class="notification-box--content">
<div class="notification-box--content op-uc-container">
<%= format_text announcement.text %>
</div>
</div>

@ -1,5 +1,5 @@
<h3 class="widget-box--header">
<div class="widget-box--header">
<div class="widget-box--header-title title-container">
<h2 class="editable-toolbar-title--fixed"><%= title %></h2>
</div>
</h3>
</div>

@ -1,5 +1,5 @@
<%= render 'homescreen/blocks/header', title: Setting.welcome_title.presence || organization_name %>
<div class="wiki">
<div class="wiki op-uc-container">
<%= format_text(Setting.welcome_text, headings: false) %>
</div>

@ -161,7 +161,7 @@ See docs/COPYRIGHT.rdoc for more details.
</div>
<% end %>
<div class="content-overlay"></div>
<div id="content-wrapper" class="<%= initial_classes %>">
<main id="content-wrapper" class="<%= initial_classes %>">
<% if show_decoration %>
<div id="breadcrumb" class="<%= initial_classes %><%= show_breadcrumb ? ' -show' : '' %>">
<%= you_are_here_info %>
@ -185,7 +185,7 @@ See docs/COPYRIGHT.rdoc for more details.
<% end %>
<%= call_hook :view_layouts_base_content %>
</div>
</div>
</main>
</div>
<div id="ajax-indicator" style="display:none;"><span><%= t(:label_loading) %></span></div>
</div>

@ -53,7 +53,7 @@ See docs/COPYRIGHT.rdoc for more details.
h2, h3 { font-size: 1.1em; }
a, a:link, a:visited { color: #2A5685;}
a:hover, a:active { color: #c61a1a; }
a.wiki-anchor { display: none; }
a.op-uc-link_permalink { display: none; }
hr {
width: 100%;
height: 1px;

@ -156,6 +156,7 @@
<li><a target="_self" href="#notifications">Notifications</a></li>
<li><a target="_self" href="#buttons">Buttons</a></li>
<li><a target="_self" href="#pagination">Pagination</a></li>
<li><a target="_self" href="#user-content">User Content</a></li>
</ul>
</nav>

@ -54,7 +54,7 @@ See docs/COPYRIGHT.rdoc for more details.
h2.emailTitle { color: #1a67a3; font-size: 2em; }
a, a:link, a:visited { color: #2A5685;}
a:hover, a:active { color: #c61a1a; }
a.wiki-anchor { display: none; }
a.op-uc-link_permalink { display: none; }
hr {
width: 100%;
height: 1px;

@ -68,7 +68,7 @@ See docs/COPYRIGHT.rdoc for more details.
<div class="forum-message">
<p class="author additional-information"><%= authoring @topic.created_at, @topic.author %></p>
<div class="wiki">
<div class="wiki op-uc-container">
<%= format_text(@topic.content, object: @topic, attachments: @topic.attachments) %>
</div>
@ -110,7 +110,7 @@ See docs/COPYRIGHT.rdoc for more details.
-
<%= authoring message.created_at, message.author %>
</h4>
<div class="wiki">
<div class="wiki op-uc-container">
<%= format_text message, :content, attachments: message.attachments %>
</div>
<% resource = message_attachment_representer(message) %>

@ -53,7 +53,7 @@ See docs/COPYRIGHT.rdoc for more details.
<%= link_to h(news.title), news_path(news) %>
<%= "(#{t(:label_x_comments, count: news.comments_count)})" if news.comments_count > 0 %></h3>
<p class="author additional-information"><%= authoring news.created_at, news.author %></p>
<div class="wiki">
<div class="wiki op-uc-container">
<%= format_text(news.summary.present? ? news.summary : truncate(news.description, length: 150, escape: false), object: news) %>
</div>
</div>

@ -44,7 +44,9 @@ See docs/COPYRIGHT.rdoc for more details.
<p><%=h version.description %></p>
<ul>
<% version.custom_values.each do |custom_value| %>
<% if !custom_value.value.blank? %>
<% if custom_value.value.present? && custom_value.custom_field.field_format == 'text' %>
<li><%=h custom_value.custom_field.name %>:<div class="op-uc-container"><%=h show_value(custom_value) %></div></li>
<% elsif custom_value.value.present? %>
<li><%=h custom_value.custom_field.name %>: <%=h show_value(custom_value) %></li>
<% end %>
<% end %>

@ -27,7 +27,7 @@ See docs/COPYRIGHT.rdoc for more details.
++#%>
<div class="wiki wiki-content highlight">
<div class="wiki wiki-content op-uc-container">
<% if @formatted_text %>
<%= @formatted_text %>
<% else %>

@ -38,9 +38,9 @@ See docs/COPYRIGHT.rdoc for more details.
ul.toc li { list-style-type:none; }
ul.toc li.heading2 { margin-left: 1em; }
ul.toc li.heading3 { margin-left: 2em; }
a.wiki-anchor { display: none; margin-left: 6px; text-decoration: none; }
a.wiki-anchor:hover { color: #aaa !important; text-decoration: none; }
h1:hover a.wiki-anchor, h2:hover a.wiki-anchor, h3:hover a.wiki-anchor { display: inline; color: #ddd; }
a.op-uc-link_permalink { display: none; margin-left: 6px; text-decoration: none; }
a.op-uc-link_permalink:hover { color: #aaa !important; text-decoration: none; }
h1:hover a.op-uc-link_permalink, h2:hover a.op-uc-link_permalink, h3:hover a.op-uc-link_permalink { display: inline; color: #ddd; }
</style>
</head>
<body>

@ -78,12 +78,6 @@
</ng-container>
<div class="attributes-group description-group">
<div class="attributes-group--header">
<div class="attributes-group--header-container">
<h3 class="attributes-group--header-text"
[textContent]="text.fields.description"></h3>
</div>
</div>
<div class="single-attribute work-packages--details--description">
<editable-attribute-field [fieldName]="'description'"
[resource]="workPackage"

@ -47,7 +47,7 @@
</div>
</div>
<div *ngIf="!active && (isComment || isBcfComment)"
class="message wiki"
class="message wiki op-uc-container"
[innerHtml]="postedComment">
</div>
<ul class="work-package-details-activities-messages" *ngIf="!isInitial">

@ -1,8 +1,7 @@
<div class="toolbar-container">
<div class="toolbar">
<div class="title-container">
<h2 [textContent]="text.boards">
</h2>
<h2 [textContent]="text.boards"></h2>
</div>
<ul class="toolbar-items"
*ngIf="showBoardIndexView()">

@ -33,5 +33,5 @@
<h2 *ngIf="!editable"
[attr.title]="selectedTitle"
[ngClass]="{ '-disabled': disabled, '-small': smallHeader }"
class="editable-toolbar-title--fixed"> {{ selectedTitle }}
class="editable-toolbar-title--fixed">{{ selectedTitle }}
</h2>

@ -39,7 +39,13 @@ export class FormattableDisplayField extends DisplayField {
public render(element:HTMLElement, displayText:string, options:any = {}):void {
let div = document.createElement('div');
div.classList.add('read-value--html', 'wiki', 'highlight', '-multiline');
div.classList.add(
'read-value--html',
'highlight',
'op-uc-container',
'op-uc-container_reduced-headings',
'-multiline',
);
if (options.rtl) {
div.classList.add('-rtl');
}

@ -16,7 +16,7 @@
</a>
</div>
<div class="op-modal--modal-body -formattable"
<div class="op-modal--modal-body -formattable op-uc-container op-uc-container__no-permalinks"
tabindex="0"
[innerHtml]="helpText.helpText.html">
</div>

@ -11,12 +11,12 @@
<ng-template #text>
<span #displayContainer
class="inline-edit--formattable-display-text -default">
<span
<div class="op-uc-container"
*ngIf="!textEmpty"
[innerHTML]="customText"></span>
<span
[innerHTML]="customText"></div>
<div
*ngIf="textEmpty"
[innerHTML]="placeholderText"></span>
[innerHTML]="placeholderText"></div>
</span>
</ng-template>

@ -22,7 +22,7 @@
<em [textContent]="documentCreated(document)"></em>
</p>
<div class="wiki grid--widget-limited-text"
<div class="wiki grid--widget-limited-text op-uc-container"
[innerHtml]="documentDescription(document)">
</div>
</ng-container>

@ -30,7 +30,7 @@
blockquote
font-style: italic
border-left: 3px solid #e0e0e0
padding-left: 0.6em
padding-left: 1.2em
margin-left: 2.4em
&.icon:before
@ -40,8 +40,5 @@ blockquote
right: 15px
padding: 0 0 0 0
#content blockquote
padding-left: 22px
.nosidebar blockquote
margin: 1em 0

@ -42,9 +42,3 @@
// Avoid large right margin for conditional button
.help-text--edit-button
margin-right: 0
// Hide the wiki-anchor
.wiki-anchor,
*:hover .wiki-anchor
display: none

@ -35,7 +35,6 @@
@import attributes_group
@import information_section
@import widget_box
@import wiki
@import list
@import work_packages
@import table
@ -78,3 +77,4 @@
@import menus/menu_blocks
@import editor/index
@import modules/index
@import user-content/index

@ -150,6 +150,7 @@ table.generic-table
tr:not(.-no-highlighting)
border-bottom: 1px solid var(--table-row-border-color)
@media screeen
td:not(.-no-ellipsis)
@include text-shortener
@ -185,6 +186,7 @@ table.generic-table
// as a result, td.-max will aways have at least a width of max-width, but it can
// become even wider.
&.-max
@media screen
width: 100%
max-width: 500px

@ -34,22 +34,22 @@ Wiki-syntax is used for most textarea-fields within OpenProject. The users have
<div class="wiki">
<h1>
Headline H1
<a href="#Heading-H1" class="wiki-anchor">¶</a>
<a href="#Heading-H1" class="op-uc-link_permalink">¶</a>
</h1>
<h2>
Headline H2
<a href="#Heading-H2" class="wiki-anchor">¶</a>
<a href="#Heading-H2" class="op-uc-link_permalink">¶</a>
</h2>
<h3>
Headline H3
<a href="#Heading-H3" class="wiki-anchor">¶</a>
<a href="#Heading-H3" class="op-uc-link_permalink">¶</a>
</h3>
<h4>
Headline H4
<a href="#Heading-H4" class="wiki-anchor">¶</a>
<a href="#Heading-H4" class="op-uc-link_permalink">¶</a>
</h4>
<h5>

@ -1,186 +0,0 @@
//-- copyright
// OpenProject is an open source project management software.
// Copyright (C) 2012-2020 the OpenProject GmbH
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2017 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See docs/COPYRIGHT.rdoc for more details.
//++
div.wiki
// ------------------- FONT -------------------
font-size: var(--wiki-default-font-size)
h1
font-size: calc(var(--wiki-default-font-size) * 1.75)
h2
font-size: calc(var(--wiki-default-font-size) * 1.75 * 0.8)
h3
font-size: calc(var(--wiki-default-font-size) * 1.75 * 0.7)
h4
font-size: calc(var(--wiki-default-font-size) * 1.75 * 0.6)
h5
font-size: calc(var(--wiki-default-font-size) * 1.75 * 0.5)
h1, h2, h3, h4, h5
margin: 1em 0
line-height: 1.5
font-weight: bold
color: #555555
text-transform: none
border-bottom: 1px dotted #bbbbbb
h1, h2
border-bottom-style: solid
// ------------------- TABLES -------------------
table:not(.work-package-table)
border: 1px solid #bbb
border-collapse: collapse
margin-bottom: 1em
td, th
border: 1px solid #bbb
text-align: left
ul, ol
margin-bottom: 0
th
background: rgba(0, 0, 0, 0.05)
padding: 10px
// ------------------- LISTINGS -------------------
ul.toc
margin-bottom: 12px
margin-right: 12px
margin-left: 0
display: table
font-size: var(--wiki-toc-ul-font-size)
.section-nav
margin-bottom: 0
margin-left: 12px
&.right
float: right
margin-left: 12px
margin-right: 0
width: auto
&.left
float: left
margin-right: 12px
margin-left: 0
width: auto
a
font-weight: normal
background-repeat: no-repeat
background-position: 0% 60%
&.icon-context:before
padding: 3px 3px 0 0
li
list-style-type: none
ul li
word-wrap: break-word
// ------------------- GENERAL -------------------
.external.icon-context:before
padding: 4px 4px 0 0
fieldset.collapsible legend
font-weight: bold
font-size: var(--wiki-toc-header-font-size)
img
vertical-align: middle
a.wiki-anchor
display: none
text-decoration: none
font-size: 16px
vertical-align: middle
padding-right: 2px
&:hover
color: #aaa !important
text-decoration: none
h1:hover, h2:hover, h3:hover
a.wiki-anchor
display: inline
color: #ddd
.wiki
p
margin-bottom: 1em
font-size: var(--wiki_default-font-size)
.quick_info .label
background: none
color: #000
font-weight: bold
font-size: var(--wiki-default-font-size)
.wiki-title
@include text-shortener
max-width: 100%
.wiki.wiki-content
overflow: auto
overflow-wrap: break-word
word-wrap: break-word
@include styled-scroll-bar
.wiki--content--attribute
.form--field-container,
.form--text-area-container
max-width: 100%
#wiki_page_parent_id
overflow: auto
.toolbar-container ~ .wiki-content
margin-top: 0
.wiki-version--details
.navigate-left
margin: 0 1.5rem 0 0
.navigate-right
margin: 0 0 0 1.5rem
span
vertical-align: middle
body.controller-wiki
.ck-content
min-height: 25vh
#breadcrumb ul.breadcrumb li.first-breadcrumb-element a
display: inline
width: auto
@include breakpoint(680px down)
.toolbar-container ~ .wiki-content
margin-top: 0

@ -90,7 +90,7 @@ ckeditor-augmented-textarea .op-ckeditor--wrapper
.document-editor__toolbar
position: sticky
top: 0px
z-index: 1
z-index: 2
// Adjust top offset to match if globally
// scrolling (content-wrapper)
@ -114,25 +114,10 @@ ckeditor-augmented-textarea .op-ckeditor--wrapper
.-large-height &
min-height: 250px
// todolist override global label style
label.todo-list__label
margin-bottom: 0
display: initial
font-size: initial
float: left
width: 0
> input
margin-top: 0
// todolist list-style
.ck-editor__editable .todo-list
margin-bottom: 0
li
list-style: none
word-break: break-word
.ck-editor__editable[dir="rtl"]
ol, ul
margin-left: 0
margin-right: 40px
.ck tr .ck-editor__nested-editable
border: 1px solid var(--ck-color-base-border)

@ -1,4 +1,3 @@
@import 'markdown'
@import 'ckeditor'
@import 'macros'
@import 'rouge'

@ -1,26 +1,12 @@
// Legacy macro rendering
macro.legacy-macro
.legacy-macro
background: $nm-color-warning-background
border: 2px dashed $nm-color-warning-border
padding: 10px 5px
line-height: 3rem
.ck-widget.macro,
macro.macro-placeholder
border: 2px dashed #ccc
min-height: 50px
display: flex
justify-content: center
align-items: center
color: #575757
background: #f8f8f8
.macro-value
font-style: italic
color: var(--gray-dark)
// Unavailable macros
macro.macro-unavailable
.macro-unavailable
@extend %error-placeholder
background: $nm-color-error-background
border-style: dashed

@ -1,58 +0,0 @@
// Specific styles for displaying rendered markdown on all pages
// This is still selected by div.wiki since this is still used throughout the app.
div.wiki,
div.ck-editor__preview
// Style pre tags alone
pre
margin: 1em 1em 1em 1.6em
padding: 2px 2px 2px 0
background-color: #fafafa
border: 1px solid #dadada
width: auto
overflow-x: auto
overflow-y: hidden
// Avoid doubling borders in pre > code
pre > code
display: block
border: none
background: transparent
color: initial
ul.task-list
list-style: none
.task-list-item
*
vertical-align: top
input
height: 25px
position: absolute
margin-left: -25px
// Style tables within figure.table
figure.table
// Copy the display style of CKEDitors table figures
// this prevents cutting of the figure if float is involved
display: table
// If a figure is present, it might set the width and height
// so we want to have the table at full width and height
> table
height: 100%
width: 100%
.task-list-item
input
position: relative
margin-right: 5px
// Ensure we break apart words in table cells that
// are restricted in width (OP#33524)
td[style*=";width:"],
td[style^="width:"],
th[style*=";width:"],
th[style^="width:"]
word-break: break-all

@ -1,5 +1,3 @@
.highlight table td { padding: 5px; }
.highlight table pre { margin: 0; }
.highlight .cm {
color: #999988;
font-style: italic;

@ -0,0 +1,45 @@
.op-uc-figure
margin: 0
display: flex
flex-direction: column
align-items: center
align-self: stretch
width: 100%
max-width: 100%
position: relative
@include styled-scroll-bar
@at-root .op-uc-container_editing &
max-height: unset
@media print
display: block
max-height: unset
&_align-end
float: right
width: auto
&_align-start
float: left
width: auto
&_align-center
// This is the current default behaviour, as ckeditor has no "don't align" option
&--content
flex-basis: auto
flex-grow: 0
flex-shrink: 1
width: 100%
display: flex
justify-content: center
&--description
flex-basis: auto
flex-grow: 1
flex-shrink: 0
padding: 0.75rem
width: 100%
text-align: center
&.table
display: flex !important

@ -0,0 +1,3 @@
.op-uc-image
max-width: 100%;
max-height: 100%;

@ -0,0 +1,30 @@
@import 'mixins'
@import 'typography'
@import 'figure'
@import 'image'
@import 'table'
@import 'list'
@import 'toc'
@import 'macros'
@import 'placeholder'
.op-uc-container
--op-uc-heading-base: 3.5rem
--op-uc-heading-falloff: 0.7
display: block
overflow: hidden
font-size: var(--wiki-default-font-size)
z-index: 0;
padding-bottom: 1rem;
// TODO: This becomes obsolete once border-box is the default
box-sizing: border-box
@include user-content-children
&_reduced-headings
--op-uc-heading-base: 1.5rem
--op-uc-heading-falloff: 0.9
&_no-permalinks *:hover .op-uc-link_permalink
display: none

@ -0,0 +1,27 @@
.op-uc-list
page-break-inside: avoid
margin-left: 2rem
&_task-list
list-style: none
&--task-checkbox
width: 1rem
height: 1rem
margin-left: -1.5rem
margin-right: 0.25rem
position: relative
top: 0.1rem
// The selectors below are needed because the CKEditor currently
// renders more nested tags than needed and its own classes
// TODO: Make these obsolete
&_task-list &--item
> span,
> label
display: inline
font: inherit
&--item
@at-root .op-uc-container_editing #{&} input[type="checkbox"]
margin-top: -0.1rem

@ -0,0 +1,16 @@
@mixin user-content-children
> * + *
margin-top: 1.5rem
> .op-uc-h1 + *,
> .op-uc-h2 + *,
> .op-uc-h3 + *,
> .op-uc-h4 + *,
> .op-uc-h5 + *
margin-top: 0
.op-uc-figure
&_align-start,
&_align-end
margin-bottom: 1rem

@ -0,0 +1,7 @@
.op-uc-placeholder
display: block
text-align: center
color: #6f6f6f
padding: 1rem
background-color: #fafafa
border: 1px solid #dadada

@ -0,0 +1,36 @@
.op-uc-table
break-inside: avoid
border-collapse: collapse
border-spacing: 0
width: 100%
@at-root .op-uc-container_editing &
border: 1px solid rgba(0, 0, 0, 0.1)
&--row
&:not(:last-child)
border-bottom: 1px solid rgba(0, 0, 0, 0.1)
@at-root .op-uc-container:not(.op-uc-container_editing) &:hover
background: rgba(26, 103, 163, 0.05)
&--cell
text-align: left
padding: 0.75rem
word-break: break-all
&:not(:last-child):not([colspan])
border-right: 1px solid rgba(0, 0, 0, 0.1)
@include user-content-children
@at-root .op-uc-container_editing &:hover
background: rgba(26, 103, 163, 0.05)
&_head
background: rgb(242, 242, 242)
background-clip: padding-box
border-bottom: 1px solid rgba(0, 0, 0, 0.1)
&.ck-editor__editable_selected
background: rgba(26, 103, 163, 0.1)

@ -0,0 +1,26 @@
.op-uc-toc
break-inside: avoid
font-size: var(--wiki-toc-ul-font-size)
background-color: #fafafa
border: 1px solid #dadada
float: left
margin: 1rem 2rem 1rem 0rem
padding: 1.5rem 1.5rem 1.5rem 0rem
&--list
padding-left: 1rem
margin: 0;
list-style: none
&--list-item
padding: 0.1em 0
&--item-link
display: flex
&--list-item-number
margin-right: 0.3rem
color: var(--body-font-color)
&--list-item-title
margin-right: 0.3rem

@ -0,0 +1,85 @@
.op-uc-h1,
.op-uc-h2,
.op-uc-h3,
.op-uc-h4,
.op-uc-h5,
.op-uc-h6,
--falloff: var(--op-uc-heading-falloff)
color: inherit
line-height: 1.6em
text-transform: none
font-weight: bold
border-bottom: 0
margin: 0
padding: 0
break-before: auto
break-after: avoid
break-inside: avoid
&:hover .op-uc-link_permalink
display: inline-flex
.op-uc-h1
font-size: var(--op-uc-heading-base)
.op-uc-h2
font-size: calc(var(--op-uc-heading-base) * var(--falloff))
.op-uc-h3
font-size: calc(var(--op-uc-heading-base) * var(--falloff) * var(--falloff))
.op-uc-h4
font-size: calc(var(--op-uc-heading-base) * var(--falloff) * var(--falloff) * var(--falloff))
.op-uc-h5
font-size: calc(var(--op-uc-heading-base) * var(--falloff) * var(--falloff) * var(--falloff) * var(--falloff))
.op-uc-p
font: inherit;
margin: 0
line-height: 1.6em
color: inherit
.op-uc-blockquote
display: block
margin: 0;
border-left: 3px solid #e0e0e0
padding: 0.8rem 1.2rem 0 1.2rem
overflow: hidden
color: #6f6f6f
@include user-content-children
.op-uc-code-block
break-inside: avoid
display: block
margin: 0
padding: 1rem
background-color: #fafafa
border: 1px solid #dadada
.op-uc-code
font-family: Consolas, "Liberation Mono", Courier, monospace
font-weight: normal
color: #333739
background-color: #fafafa
border: 1px solid #dadada
padding: 0.125em 0.3125em
break-inside: avoid
.op-uc-link
color: var(--content-link-color)
font-size: 1em
&:hover
color: var(--content-link-hover-active-color)
&_permalink
display: none
text-decoration: none
align-items: center
color: #ccc
margin-left: 0.5em
&::before
font-size: 1em
&:hover
color: #aaa
text-decoration: none

@ -107,6 +107,7 @@ html:not(.-browser-mobile)
width: 60px
// Override the default td line-height
line-height: initial !important
white-space: nowrap;
// Show context menu button when hovering
.wp-table--context-menu-td a
@ -130,6 +131,10 @@ html:not(.-browser-mobile)
display: inline-block
vertical-align: middle
width: 100%
@media print
white-space: normal
.wp-table--cell-td.-editing &
display: block
width: initial !important

@ -28,7 +28,7 @@
overflow: initial
#content-wrapper
width: 99%
width: 100vw
margin: 0
border: 0
background: #fff

@ -216,6 +216,12 @@ $nm-color-success-background: #d8fdd1
@include text-shortener
padding: 0
// WYSIWYG content creates bigger headings than this. When viewing on screen, this is okay since the general page
// layout does a decent job conveying hierarchy. However, when printing we need to bump the size of this heading
// (which is really the page heading) to be larger than the user-content h1.
@media print
font-size: 4rem
div.inline-edit
cursor: pointer

@ -69,6 +69,9 @@ body.router--work-packages-partitioned-split-view-new
border: 1px solid #eeeeee
padding: 0 1rem 10px
@media print
display: none;
.button
margin: .5rem .5rem 0 0

@ -155,7 +155,7 @@
margin-left: 0
#work-packages-index
.wiki-anchor
.op-uc-link_permalink
display: none
.work-packages--show-view

@ -50,11 +50,17 @@ $table-timeline--compact-row-height: 28px
overflow: auto
@include styled-scroll-bar
@media print
overflow: hidden
// Disable css containment since we have no inner elements
.work-packages-tabletimeline--table-side,
.work-packages-tabletimeline--timeline-side
contain: initial !important
@media print
max-width: 100%
.work-package-table--container
overflow: visible

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -33,7 +33,7 @@ module API
class Collection < ::API::Decorators::Single
include API::Utilities::UrlHelper
def initialize(models, total, self_link, current_user:)
def initialize(models, total, self_link:, current_user:)
@total = total
@self_link = self_link

@ -36,7 +36,7 @@ module API
relation.base_class.per_page
end
def initialize(models, self_link, query: {}, page: nil, per_page: nil, current_user:)
def initialize(models, self_link:, query: {}, page: nil, per_page: nil, current_user:)
@self_link_base = self_link
@query = query
@page = page.to_i > 0 ? page.to_i : 1
@ -47,7 +47,7 @@ module API
full_self_link = make_page_link(page: @page, page_size: @per_page)
paged = paged_models(models)
super(paged, models.count, full_self_link, current_user: current_user)
super(paged, models.count, self_link: full_self_link, current_user: current_user)
end
link :jumpTo do

@ -235,9 +235,9 @@ module API
include InstanceMethods
def self.create(represented, self_link = nil, current_user:, form_embedded: false)
def self.create(represented, current_user:, self_link: nil, form_embedded: false)
new(represented,
self_link,
self_link: self_link,
current_user: current_user,
form_embedded: form_embedded)
end
@ -252,8 +252,8 @@ module API
end
def initialize(represented,
self_link = nil,
current_user:,
self_link: nil,
form_embedded: false)
self.form_embedded = form_embedded

@ -30,8 +30,8 @@
module API
module Decorators
class UnpaginatedCollection < ::API::Decorators::Collection
def initialize(models, self_link, current_user:)
super(models, model_count(models), self_link, current_user: current_user)
def initialize(models, self_link:, current_user:)
super(models, model_count(models), self_link: self_link, current_user: current_user)
end
def model_count(models)

@ -39,7 +39,7 @@ module API
@activities = get_aggregated_journals
self_link = api_v3_paths.work_package_activities @work_package.id
Activities::ActivityCollectionRepresenter.new(@activities,
self_link,
self_link: self_link,
current_user: current_user)
end

@ -73,7 +73,7 @@ module API
def attachments
::API::V3::Attachments::AttachmentCollectionRepresenter.new(attachment_set,
attachments_by_resource,
self_link: attachments_by_resource,
current_user: current_user)
end

@ -161,7 +161,7 @@ module API
-> do
attachments = container.attachments
AttachmentCollectionRepresenter.new(attachments,
get_attachment_self_path,
self_link: get_attachment_self_path,
current_user: current_user)
end
end

@ -41,7 +41,8 @@ module API
get do
self_link = api_v3_paths.categories_by_project(@project.identifier)
CategoryCollectionRepresenter.new(@categories, self_link, current_user: current_user)
CategoryCollectionRepresenter
.new(@categories, self_link: self_link, current_user: current_user)
end
end
end

@ -36,7 +36,7 @@ module API
resources :help_texts do
get do
@entries = AttributeHelpText.visible(current_user)
HelpTextCollectionRepresenter.new(@entries, api_v3_paths.help_texts, current_user: current_user)
HelpTextCollectionRepresenter.new(@entries, self_link: api_v3_paths.help_texts, current_user: current_user)
end
route_param :id, type: Integer, desc: 'Help text ID' do

@ -31,9 +31,9 @@ module API
module Memberships
module Schemas
class MembershipSchemaRepresenter < ::API::Decorators::SchemaRepresenter
def initialize(represented, self_link = nil, current_user: nil, form_embedded: false)
def initialize(represented, self_link: nil, current_user: nil, form_embedded: false)
super(represented,
self_link,
self_link: self_link,
current_user: current_user,
form_embedded: form_embedded)
end

@ -40,7 +40,7 @@ module API
if query.valid?
NewsCollectionRepresenter.new(query.results,
api_v3_paths.newses,
self_link: api_v3_paths.newses,
page: to_i_or_nil(params[:offset]),
per_page: resolve_page_size(params[:pageSize]),
current_user: current_user)

@ -43,7 +43,7 @@ module API
.includes(:preference)
::API::V3::Users::PaginatedUserCollectionRepresenter.new(principals,
api_v3_paths.principals,
self_link: api_v3_paths.principals,
page: to_i_or_nil(params[:offset]),
per_page: resolve_page_size(params[:pageSize]),
current_user: current_user)

@ -43,7 +43,7 @@ module API
get do
PriorityCollectionRepresenter.new(@priorities,
api_v3_paths.priorities,
self_link: api_v3_paths.priorities,
current_user: current_user)
end

@ -41,7 +41,7 @@ module API
available_assignees = @project.possible_assignees.includes(:preference)
self_link = api_v3_paths.available_assignees(@project.id)
Users::UserCollectionRepresenter.new(available_assignees,
self_link,
self_link: self_link,
current_user: current_user)
end
end

@ -41,7 +41,7 @@ module API
available_responsibles = @project.possible_responsibles.includes(:preference)
self_link = api_v3_paths.available_responsibles(@project.id)
Users::UserCollectionRepresenter.new(available_responsibles,
self_link,
self_link: self_link,
current_user: current_user)
end
end

@ -41,7 +41,7 @@ module API
self.to_eager_load = ::API::V3::Projects::ProjectRepresenter.to_eager_load
self.checked_permissions = ::API::V3::Projects::ProjectRepresenter.checked_permissions
def initialize(models, self_link, current_user:)
def initialize(models, self_link:, current_user:)
super
@represented = ::API::V3::Projects::ProjectEagerLoadingWrapper.wrap(represented)

@ -76,7 +76,7 @@ module API
self_link = api_v3_paths.query_available_projects
::API::V3::Projects::ProjectCollectionRepresenter.new(available_projects,
self_link,
self_link: self_link,
current_user: current_user)
end
end

@ -34,9 +34,9 @@ module API
class QueryCollectionRepresenter < ::API::Decorators::UnpaginatedCollection
element_decorator ::API::V3::Queries::QueryRepresenter
def initialize(models, self_link, current_user:)
def initialize(models, self_link:, current_user:)
super(models.includes(::API::V3::Queries::QueryRepresenter.to_eager_load),
self_link,
self_link: self_link,
current_user: current_user)
end

@ -50,7 +50,7 @@ module API
filters = Query.new.available_filters
collection_representer.new(filters,
api_v3_paths.query_filter_instance_schemas,
self_link: api_v3_paths.query_filter_instance_schemas,
current_user: current_user)
end
@ -65,7 +65,7 @@ module API
filter = filter_class.create! name: ar_name, context: OpenStruct.new(project: nil)
single_representer.new(filter,
api_v3_paths.query_filter_instance_schema(params[:id]),
self_link: api_v3_paths.query_filter_instance_schema(params[:id]),
current_user: current_user)
end
end

@ -42,7 +42,7 @@ module API
filters = Query.new(project: @project).available_filters
representer.new(filters,
api_v3_paths.query_project_filter_instance_schemas(@project.id),
self_link: api_v3_paths.query_project_filter_instance_schemas(@project.id),
current_user: current_user)
end
end

@ -40,7 +40,7 @@ module API
get do
representer.new(Query.new(project: @project),
api_v3_paths.query_project_schema(@project.id),
self_link: api_v3_paths.query_project_schema(@project.id),
current_user: current_user,
form_embedded: false)
end

@ -44,7 +44,7 @@ module API
get do
representer.new(Query.new,
api_v3_paths.query_schema,
self_link: api_v3_paths.query_schema,
current_user: current_user,
form_embedded: false)
end

@ -36,9 +36,9 @@ module API
module Queries
module Schemas
class QuerySchemaRepresenter < ::API::Decorators::SchemaRepresenter
def initialize(represented, self_link = nil, current_user: nil, form_embedded: false)
def initialize(represented, self_link: nil, current_user: nil, form_embedded: false)
super(represented,
self_link,
self_link: self_link,
current_user: current_user,
form_embedded: form_embedded)
end
@ -263,7 +263,7 @@ module API
.reject { |f| f.is_a?(::Queries::WorkPackages::Filter::RelatableFilter) }
QueryFilterInstanceSchemaCollectionRepresenter.new(filters,
filter_instance_schemas_href,
self_link: filter_instance_schemas_href,
form_embedded: form_embedded,
current_user: current_user)
end

@ -41,7 +41,7 @@ module API
self_path = api_v3_paths.work_package_revisions(work_package.id)
revisions = work_package.changesets.visible
RevisionsCollectionRepresenter.new(revisions, self_path, current_user: current_user)
RevisionsCollectionRepresenter.new(revisions, self_link: self_path, current_user: current_user)
end
end
end

@ -32,10 +32,10 @@ module API
module Schemas
class SchemaCollectionRepresenter <
::API::Decorators::UnpaginatedCollection
def initialize(represented, self_link, current_user:, form_embedded: false)
def initialize(represented, self_link:, current_user:, form_embedded: false)
self.form_embedded = form_embedded
super(represented, self_link, current_user: current_user)
super(represented, self_link: self_link, current_user: current_user)
end
collection :elements,
@ -44,7 +44,7 @@ module API
self_link = model_self_link(model)
element_decorator.create(model,
self_link,
self_link: self_link,
current_user: current_user,
form_embedded: form_embedded)
end

@ -41,7 +41,7 @@ module API
get do
StatusCollectionRepresenter.new(Status.all,
api_v3_paths.statuses,
self_link: api_v3_paths.statuses,
current_user: current_user)
end

@ -41,7 +41,10 @@ module API
get do
types = Type.includes(:color).all
TypeCollectionRepresenter.new(types, api_v3_paths.types, current_user: current_user)
TypeCollectionRepresenter
.new(types,
self_link: api_v3_paths.types,
current_user: current_user)
end
route_param :id, type: Integer, desc: 'Type ID' do

@ -41,7 +41,7 @@ module API
get do
types = @project.types
TypeCollectionRepresenter.new(types,
api_v3_paths.types_by_project(@project.id),
self_link:api_v3_paths.types_by_project(@project.id),
current_user: current_user)
end
end

@ -65,7 +65,7 @@ module API
if query.valid?
users = query.results.includes(:preference)
PaginatedUserCollectionRepresenter.new(users,
api_v3_paths.users,
self_link: api_v3_paths.users,
page: to_i_or_nil(params[:offset]),
per_page: resolve_page_size(params[:pageSize]),
current_user: current_user)

@ -386,9 +386,9 @@ module API
custom_field_class(custom_fields)
end
def create(*args)
create_class(args.first, args.last[:current_user])
.new(*args)
def create(represented, **args)
create_class(represented, args[:current_user])
.new(represented, **args)
end
def custom_field_class(custom_fields)

@ -84,7 +84,7 @@ module API
def render_paginated_success(results, params, self_path)
render_representer
.new(results,
self_path,
self_link: self_path,
page: to_i_or_nil(params[:offset]),
per_page: resolve_page_size(params[:pageSize]),
current_user: User.current)
@ -93,7 +93,7 @@ module API
def render_unpaginated_success(results, self_path)
render_representer
.new(results,
self_path,
self_link: self_path,
current_user: User.current)
end

@ -66,7 +66,7 @@ module API
representer
.create(contract_instance,
self_path,
self_link: self_path,
current_user: User.current)
end

@ -67,7 +67,7 @@ module API
end
representer.new(scope,
link,
self_link: link,
current_user: current_user)
end

@ -43,7 +43,10 @@ module API
get do
path = api_v3_paths.projects_by_version @version.id
Projects::ProjectCollectionRepresenter.new(@projects, path, current_user: current_user)
Projects::ProjectCollectionRepresenter
.new(@projects,
self_link: path,
current_user: current_user)
end
end
end

@ -37,9 +37,9 @@ module API
custom_field_injector type: :schema_representer
def initialize(represented, self_link = nil, current_user: nil, form_embedded: false)
def initialize(represented, self_link: nil, current_user: nil, form_embedded: false)
super(represented,
self_link,
self_link: self_link,
current_user: current_user,
form_embedded: form_embedded)
end

@ -57,7 +57,7 @@ module API
self_link = api_v3_paths.available_projects_on_create(params[:for_type])
Projects::ProjectCollectionRepresenter.new(available_projects,
self_link,
self_link: self_link,
current_user: current_user)
end
end

@ -46,7 +46,7 @@ module API
.includes(Projects::ProjectCollectionRepresenter.to_eager_load)
self_link = api_v3_paths.available_projects_on_edit(@work_package.id)
Projects::ProjectCollectionRepresenter.new(available_projects,
self_link,
self_link: self_link,
current_user: current_user)
end
end

@ -51,7 +51,7 @@ module API
schema_link = api_v3_paths.work_package_schema(represented.project_id,
represented.type_id)
Schema::WorkPackageSchemaRepresenter.create(schema,
nil,
self_link: nil,
form_embedded: true,
base_schema_link: schema_link,
current_user: current_user)

@ -83,10 +83,10 @@ module API
end
end
def initialize(schema, self_link, context)
def initialize(schema, self_link:, **context)
@base_schema_link = context.delete(:base_schema_link) || nil
@show_lock_version = !context.delete(:hide_lock_version)
super(schema, self_link, **context)
super(schema, self_link: self_link, **context)
end
link :baseSchema do

@ -82,7 +82,7 @@ module API
end
WorkPackageSchemaCollectionRepresenter.new(schemas,
schemas_path_with_filters_params,
self_link: schemas_path_with_filters_params,
current_user: current_user)
end
@ -113,7 +113,7 @@ module API
schema = TypedWorkPackageSchema.new(project: @project, type: @type)
self_link = api_v3_paths.work_package_schema(@project.id, @type.id)
represented_schema = WorkPackageSchemaRepresenter.create(schema,
self_link,
self_link: self_link,
current_user: current_user)
with_etag! represented_schema.json_cache_key

@ -44,7 +44,7 @@ module API
users = query.results.merge(@work_package.addable_watcher_users).includes(:preference)
::API::V3::Users::PaginatedUserCollectionRepresenter.new(
users,
api_v3_paths.users,
self_link: api_v3_paths.users,
page: to_i_or_nil(params[:offset]),
per_page: resolve_page_size(params[:pageSize]),
current_user: current_user
@ -60,7 +60,7 @@ module API
watchers = @work_package.watcher_users.active_or_registered
self_link = api_v3_paths.work_package_watchers(@work_package.id)
Users::UserCollectionRepresenter.new(watchers,
self_link,
self_link: self_link,
current_user: current_user)
end
end

@ -35,7 +35,7 @@ module API
element_decorator ::API::V3::WorkPackages::WorkPackageRepresenter
def initialize(models,
self_link,
self_link:,
query: {},
project: nil,
groups:,
@ -50,7 +50,7 @@ module API
@embed_schemas = embed_schemas
super(models,
self_link,
self_link: self_link,
query: query,
page: page,
per_page: per_page,
@ -181,7 +181,7 @@ module API
end
Schema::WorkPackageSchemaCollectionRepresenter.new(schemas,
schemas_path,
self_link: schemas_path,
current_user: current_user)
end

@ -47,7 +47,7 @@ module API
::API::V3::Relations::RelationCollectionRepresenter.new(
relations,
api_v3_paths.work_package_relations(@work_package.id),
self_link: api_v3_paths.work_package_relations(@work_package.id),
current_user: current_user
)
end

@ -540,7 +540,7 @@ module API
.includes(::API::V3::Relations::RelationCollectionRepresenter.to_eager_load)
::API::V3::Relations::RelationCollectionRepresenter.new(visible_relations,
self_path,
self_link: self_path,
current_user: current_user)
end

@ -51,7 +51,9 @@ module OpenProject::TextFormatting
def default_autolink_options
{
enabled: true,
classes: 'rinku-autolink'
# Having to specify the link class again here is unfortunate. But as rinku seems to run latest,
# it cannot receive the link class like all the rest of the links.
classes: 'op-uc-link'
}
end
end

@ -0,0 +1,94 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
module OpenProject::TextFormatting
module Filters
class BemCssFilter < HTML::Pipeline::Filter
BEM_CLASSES = {
h1: 'op-uc-h1',
h2: 'op-uc-h2',
h3: 'op-uc-h3',
h4: 'op-uc-h4',
h5: 'op-uc-h5',
h6: 'op-uc-h6',
p: 'op-uc-p',
blockquote: 'op-uc-blockquote',
code: 'op-uc-code',
pre: 'op-uc-code-block',
li: 'op-uc-list--item',
ul: 'op-uc-list',
ol: 'op-uc-list',
a: 'op-uc-link',
figure: 'op-uc-figure',
img: 'op-uc-image',
figcaption: 'op-uc-figure--description',
table: 'op-uc-table',
thead: 'op-uc-table--head',
tr: 'op-uc-table--row',
td: 'op-uc-table--cell',
th: 'op-uc-table--cell op-uc-table--cell_head'
}.with_indifferent_access.freeze
# Contains all elements with their classes which should not be modified
# as they already have the correct BEM class.
UNMODIFIED = {
h1: 'op-uc-toc--title',
li: 'op-uc-toc--list-item',
ul: 'op-uc-toc--list'
}.with_indifferent_access.freeze
def call
doc.search(*BEM_CLASSES.keys.map(&:to_s)).each do |element|
add_css_class(element, BEM_CLASSES[element.name]) unless not_to_be_modified?(element)
end
doc
end
private
def not_to_be_modified?(element)
element['class'].present? &&
UNMODIFIED[element.name] &&
element['class'].include?(UNMODIFIED[element.name])
end
def add_css_class(element, css_class)
if element['class'].present?
# Avoid using element['class'].include?(css_class) as css_class can be a substring
# of an existing class
element['class'] += " #{css_class}" unless element['class'].split.any? { |existing_class| existing_class == css_class }
else
element['class'] = css_class
end
end
end
end
end

@ -0,0 +1,87 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
module OpenProject::TextFormatting
module Filters
class FigureWrappedFilter < HTML::Pipeline::Filter
include ActionView::Context
include ActionView::Helpers::TagHelper
def call
doc.search('table', 'img').each do |element|
case element.name
when 'img', 'table'
wrap_element(element)
else
# nothing
end
end
doc
end
private
# Wrap img elements like this
# <figure>
# <div class="op-uc-figure--content">
# <img></img>
# </div>
# <figure>
#
# and
#
# <figure>
# <div class="op-uc-figure--content">
# <table></table>
# </div>
# <figure>
# The figure and img/table element later on get css classes applied to them so it does
# not have to happen here.
def wrap_element(element)
wrap_in_div(element)
wrap_in_figure(element.parent)
end
def wrap_in_figure(element)
element.wrap('<figure>') unless element.parent&.name == 'figure'
end
def wrap_in_div(element)
element.wrap('<div>') unless element.parent&.name == 'div'
div = element.parent
div['class'] = 'op-uc-figure--content'
end
end
end
end

@ -42,7 +42,7 @@ module OpenProject::TextFormatting
def call
doc.search('macro').each do |macro|
registered.each do |macro_class|
next unless Array(macro['class']).include? macro_class.identifier
next unless macro_applies?(macro_class, macro)
# If requested to skip macro expansion, do that
if context[:disable_macro_expansion]
@ -65,6 +65,8 @@ module OpenProject::TextFormatting
doc
end
private
def macro_error_placeholder(macro_class, message)
ApplicationController.helpers.content_tag :macro,
"#{I18n.t(:macro_execution_error, macro_name: macro_class.identifier)} (#{message})",
@ -78,6 +80,10 @@ module OpenProject::TextFormatting
class: 'macro-placeholder',
data: { macro_name: macro_class.identifier }
end
def macro_applies?(macro_class, element)
((element['class'] || '').split & Array(macro_class.identifier)).any?
end
end
end
end

@ -38,8 +38,8 @@ module OpenProject::TextFormatting::Filters::Macros
HTML_CLASS
end
def apply(*_args)
# Nothing to do
def apply(macro, result:, context:)
macro['class'] = macro['class'].gsub('op-uc-placeholder', '').squish
end
def is?(macro)

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

Loading…
Cancel
Save