fontcustom_canvas 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +7 -4
- data/fontcustom_canvas-0.1.0.gem +0 -0
- data/fontcustom_canvas-0.1.1.gem +0 -0
- data/fontcustom_canvas.gemspec +1 -0
- data/lib/fontcustom_canvas.rb +5 -5
- data/lib/fontcustom_canvas/version.rb +1 -1
- data/public/_ic-typography.scss +629 -0
- data/public/_ic_app_header.scss +463 -0
- data/public/_variables.scss +298 -0
- data/public/brandable_css.rb +374 -0
- data/public/brandable_variables.json +233 -0
- data/public/theme_editor/Fonts.js +92 -0
- data/public/theme_editor/PropTypes.js +130 -0
- data/public/theme_editor/ThemeEditorAccordion.js +131 -0
- data/public/theme_editor/ThemeEditorFontFamilyRow.js +147 -0
- data/public/theme_editor/ThemeEditorFontSizeRow.js +152 -0
- data/public/theme_editor/ThemeEditorFontWeightRow.js +176 -0
- metadata +30 -3
@@ -0,0 +1,298 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) 2014 - present Instructure, Inc.
|
3
|
+
*
|
4
|
+
* This file is part of Canvas.
|
5
|
+
*
|
6
|
+
* Canvas is free software: you can redistribute it and/or modify it under
|
7
|
+
* the terms of the GNU Affero General Public License as published by the Free
|
8
|
+
* Software Foundation, version 3 of the License.
|
9
|
+
*
|
10
|
+
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
11
|
+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
12
|
+
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
13
|
+
* details.
|
14
|
+
*
|
15
|
+
* You should have received a copy of the GNU Affero General Public License along
|
16
|
+
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
*/
|
18
|
+
|
19
|
+
/// TOC
|
20
|
+
//============================================================================================
|
21
|
+
//
|
22
|
+
// - Canvas Brand Variants
|
23
|
+
// - Custom Branding
|
24
|
+
// - Canvas LMS Color Sheet
|
25
|
+
// - Canvas Theme Color Variables
|
26
|
+
//
|
27
|
+
//============================================================================================
|
28
|
+
|
29
|
+
// This imports the variables needed to support accessibility ($use_high_contrast)
|
30
|
+
// You can also use the sass function that helps ensure color contrast ratio.
|
31
|
+
// Look in /sass-functions/ for more information on how that is used
|
32
|
+
@import "variant_variables";
|
33
|
+
@import 'https://fonts.googleapis.com/css?family=Abel|Abril+Fatface|Acme|Alegreya|Alegreya+Sans|Anton|Archivo|Archivo+Black|Archivo+Narrow|Arimo|Arvo|Asap|Asap+Condensed|Bitter|Bowlby+One+SC|Bree+Serif|Cabin|Cairo|Catamaran|Crete+Round|Crimson+Text|Cuprum|Dancing+Script|Dosis|Droid+Sans|Droid+Serif|EB+Garamond|Exo|Exo+2|Faustina|Fira+Sans|Fjalla+One|Francois+One|Gloria+Hallelujah|Hind|Inconsolata|Indie+Flower|Josefin+Sans|Julee|Karla|Lato|Libre+Baskerville|Libre+Franklin|Lobster|Lora|Mada|Manuale|Maven+Pro|Merriweather|Merriweather+Sans|Montserrat|Montserrat+Subrayada|Mukta+Vaani|Muli|Noto+Sans|Noto+Serif|Nunito|Open+Sans|Open+Sans+Condensed:300|Oswald|Oxygen|PT+Sans|PT+Sans+Caption|PT+Sans+Narrow|PT+Serif|Pacifico|Passion+One|Pathway+Gothic+One|Play|Playfair+Display|Poppins|Questrial|Quicksand|Raleway|Roboto|Roboto+Condensed|Roboto+Mono|Roboto+Slab|Ropa+Sans|Rubik|Saira|Saira+Condensed|Saira+Extra+Condensed|Saira+Semi+Condensed|Sedgwick+Ave|Sedgwick+Ave+Display|Shadows+Into+Light|Signika|Slabo+27px|Source+Code+Pro|Source+Sans+Pro|Spectral|Titillium+Web|Ubuntu|Ubuntu+Condensed|Varela+Round|Vollkorn|Work+Sans|Yanone+Kaffeesatz|Zilla+Slab|Zilla+Slab+Highlight|Nerko+One|Xanh+Mono|Texturina|Lobster|Dancing+Script|Architects+Daughter|Modak|Amatic+SC';
|
34
|
+
|
35
|
+
|
36
|
+
//=======================
|
37
|
+
// Canvas LMS Color Sheet
|
38
|
+
//=======================
|
39
|
+
// Our color variables in Canvas are simple and easy to integrate
|
40
|
+
// We use a two-tiered variable process with Canvas color variables.
|
41
|
+
// When you need to use a color, please create a functional variable name
|
42
|
+
// and use the color variable name of your choosing. See examples below.
|
43
|
+
|
44
|
+
// These "@if $use_high_contrast ..." conditions need to be run before we load
|
45
|
+
// the autogenerated brandable variables because we are setting up the correct
|
46
|
+
// "default value" for it to use.
|
47
|
+
|
48
|
+
//====================================
|
49
|
+
// Abstract Color Variables
|
50
|
+
//====================================
|
51
|
+
$electric: #008EE2; // blue
|
52
|
+
@if $use_high_contrast { $electric: #0770A3; }
|
53
|
+
$shamrock: #00AC18; // green
|
54
|
+
@if $use_high_contrast { $shamrock: #127A1B; }
|
55
|
+
$barney: #BF32A4; // magenta
|
56
|
+
@if $use_high_contrast { $barney: #B8309E; }
|
57
|
+
$crimson: #EE0612; // red
|
58
|
+
@if $use_high_contrast { $crimson: #D01A19; }
|
59
|
+
$fire: #FC5E13; // orange
|
60
|
+
@if $use_high_contrast { $fire: #C23C0D; }
|
61
|
+
|
62
|
+
//====================================
|
63
|
+
// Default Functional Swatches
|
64
|
+
//====================================
|
65
|
+
$ic-color-success: $shamrock;
|
66
|
+
$ic-color-action: $barney;
|
67
|
+
$ic-color-danger: $crimson;
|
68
|
+
$ic-color-alert: $fire;
|
69
|
+
|
70
|
+
//====================================
|
71
|
+
// Gray-ish Scale
|
72
|
+
//====================================
|
73
|
+
|
74
|
+
$ic-color-dark: #2D3B45; // licorice
|
75
|
+
$ic-color-medium-darker: #394B58; // oxford
|
76
|
+
$ic-color-medium: #73818C; // slate
|
77
|
+
@if $use_high_contrast { $ic-color-medium: #556572; }
|
78
|
+
$ic-color-medium-lighter: #8B969E; // ash
|
79
|
+
@if $use_high_contrast { $ic-color-medium-lighter: #556572; }
|
80
|
+
$heather: #A5AFB5; // heather
|
81
|
+
@if $use_high_contrast { $ic-border-dark: #556572; }
|
82
|
+
$tiara: #C7CDD1; // tiara
|
83
|
+
@if $use_high_contrast { $ic-border-color: #667887; }
|
84
|
+
$ic-color-medium-light: #F5F5F5; // porcelain
|
85
|
+
@if $use_high_contrast { $ic-color-medium-light: #FFFFFF; }
|
86
|
+
$ic-color-light: #FFFFFF; // white
|
87
|
+
|
88
|
+
|
89
|
+
//================================
|
90
|
+
// Global light background colors
|
91
|
+
//================================
|
92
|
+
// These background color variables can be used on hover states or focus states
|
93
|
+
// and meet our contrast needs when used with our main color variables
|
94
|
+
|
95
|
+
$ic-bg-light-neutral: $ic-color-medium-light;
|
96
|
+
$ic-bg-light-neutral-text: #394B58;
|
97
|
+
@if $use_high_contrast { $ic-bg-light-neutral: #EBEDEE; }
|
98
|
+
$ic-bg-light-primary: #E5F2F8;
|
99
|
+
@if $use_high_contrast { $ic-bg-light-primary: #E6F1F7;}
|
100
|
+
$ic-bg-light-primary-text: #0078BD;
|
101
|
+
@if $use_high_contrast { $ic-bg-light-primary-text: #0770A3; }
|
102
|
+
$ic-bg-light-success: #E8F6E9;
|
103
|
+
@if $use_high_contrast { $ic-bg-light-success: #E8F2E9; }
|
104
|
+
$ic-bg-light-success-text: #008A13;
|
105
|
+
@if $use_high_contrast { $ic-bg-light-success-text: $ic-color-success; }
|
106
|
+
$ic-bg-light-alert: #FBEDE7;
|
107
|
+
@if $use_high_contrast { $ic-bg-light-alert: #F9ECE8; }
|
108
|
+
$ic-bg-light-alert-text: #D14604;
|
109
|
+
@if $use_high_contrast { $ic-bg-light-alert-text: $ic-color-alert; }
|
110
|
+
$ic-bg-light-danger: #FCE8E7;
|
111
|
+
@if $use_high_contrast { $ic-bg-light-danger: #FBE8E8; }
|
112
|
+
$ic-bg-light-danger-text: #EE0612;
|
113
|
+
@if $use_high_contrast { $ic-bg-light-danger-text: $ic-color-danger; }
|
114
|
+
|
115
|
+
//====================================
|
116
|
+
// DEPRECATED COLORS - DO NOT USE
|
117
|
+
//====================================
|
118
|
+
|
119
|
+
$ic-color-neutral: hsl(0,0, 90%);
|
120
|
+
$gray-darker: $ic-color-dark;
|
121
|
+
$gray-dark: $ic-color-medium-darker;
|
122
|
+
$gray: $ic-color-medium;
|
123
|
+
$gray-light: $ic-color-medium-light;
|
124
|
+
$gray-lighter: $ic-color-light;
|
125
|
+
|
126
|
+
//==================
|
127
|
+
// Layout Variables
|
128
|
+
//==================
|
129
|
+
$right_side_width: 286px;
|
130
|
+
$right_side_margin: 13px;
|
131
|
+
$left_side_width: 175px;
|
132
|
+
$min_main_width: 510px;
|
133
|
+
$max_main_width: 1100px;
|
134
|
+
$ic-sp: 12px;
|
135
|
+
$ic-border-radius: $ic-sp/2;
|
136
|
+
$spacing-width: 20px; // TODO - would be nice to phase this one out for $ic-sp
|
137
|
+
$borderRadius: 4px;
|
138
|
+
$contentBoxPadding: 8px;
|
139
|
+
|
140
|
+
//============================
|
141
|
+
// Typography Variables
|
142
|
+
//============================
|
143
|
+
|
144
|
+
// Placeholder for old bootstrap variable; deprecated, but still in use some places
|
145
|
+
// Once all of those have been adjusted to use the new variable we can get rid of this
|
146
|
+
$ic-line-height: 1.5;
|
147
|
+
|
148
|
+
$ic-font-family: var(--ic-brand-font-family, "Lato Extended", "Lato", "Helvetica Neue", Helvetica, Arial, sans-serif);
|
149
|
+
$ic-font-family-monospace: Monaco, Menlo, Consolas, "Courier New", monospace;
|
150
|
+
|
151
|
+
$ic-font-weight: var(--ic-brand-font-weight, normal); // we can phase this var out now we're on Lato
|
152
|
+
$ic-font-weight-bold: bold;
|
153
|
+
|
154
|
+
|
155
|
+
$ic-font-size: var(--ic-brand-font-size, 16px);
|
156
|
+
|
157
|
+
$ic-font-size--xxlarge: $ic-font-size + 22;
|
158
|
+
$ic-font-size--xlarge: $ic-font-size + 16;
|
159
|
+
$ic-font-size--large: $ic-font-size + 10;
|
160
|
+
$ic-font-size--medium: $ic-font-size + 4;
|
161
|
+
$ic-font-size--small: $ic-font-size;
|
162
|
+
$ic-font-size--xsmall: $ic-font-size - 2;
|
163
|
+
|
164
|
+
/* Legacy variables. Discontinue to use these: */
|
165
|
+
$h1-font-size: 23px;
|
166
|
+
$h2-font-size: 14px;
|
167
|
+
$h3-font-size: 19px;
|
168
|
+
|
169
|
+
//============================
|
170
|
+
// Layout Functional Variables
|
171
|
+
//============================
|
172
|
+
$ic-body-background-color: lighten($ic-color-neutral, 4);
|
173
|
+
$ic-content-background-color: $ic-color-light;
|
174
|
+
$ic-content-padding: 15px;
|
175
|
+
$ic-header-background: #34444f;
|
176
|
+
$ic-header-primary-width: 100px;
|
177
|
+
$ic-header-primary-expanded-width: $ic-sp*15;
|
178
|
+
$ic-right-side-width: $ic-sp*24;
|
179
|
+
$ic-breadcrumbs-height: 4.5rem;
|
180
|
+
|
181
|
+
//============================
|
182
|
+
// List Functional Variables
|
183
|
+
//============================
|
184
|
+
$ic-list-item-background--hover: #eef7ff;
|
185
|
+
$ic-list-item-background--selected: #d9edf9;
|
186
|
+
|
187
|
+
//=====================
|
188
|
+
// Global border colors
|
189
|
+
//=====================
|
190
|
+
$ic-border-color: $tiara;
|
191
|
+
// If it's a light border, it should be this color.
|
192
|
+
$ic-border-light: $tiara;
|
193
|
+
// If it's a dark border, it should be this color.
|
194
|
+
// the most often use case for this is when the line is
|
195
|
+
// dashed on a light gray background so it visually
|
196
|
+
// looks the same as the outer border
|
197
|
+
$ic-border-dark: $heather;
|
198
|
+
|
199
|
+
//=====================
|
200
|
+
// Text-color variables
|
201
|
+
//=====================
|
202
|
+
$ic-font-color-light: $ic-color-light;
|
203
|
+
$ic-font-color-dark: var(--ic-brand-font-color-dark);
|
204
|
+
@if $use_high_contrast { $ic-font-color-dark: $ic-color-dark; }
|
205
|
+
$ic-font-color--subdued: var(--ic-brand-font-color-dark-lightened-15);
|
206
|
+
@if $use_high_contrast { $ic-font-color--subdued: $ic-color-medium-darker; }
|
207
|
+
$ic-hint-text: var(--ic-brand-font-color-dark-lightened-30);
|
208
|
+
@if $use_high_contrast { $ic-hint-text: $ic-color-medium; }
|
209
|
+
|
210
|
+
// textColor is a deprecated Bootstrap 2 variable. Please use $ic-font-color-dark!
|
211
|
+
$textColor: $ic-font-color-dark; // deprecated - do not use
|
212
|
+
|
213
|
+
//=============================
|
214
|
+
// Link-color-related variables
|
215
|
+
//=============================
|
216
|
+
$ic-icon-link-color-hover: var(--ic-brand-font-color-dark-lightened-15);
|
217
|
+
@if $use_high_contrast {
|
218
|
+
$ic-icon-link-color-hover: $ic-font-color-dark;
|
219
|
+
}
|
220
|
+
|
221
|
+
$ic-icon-link-color: var(--ic-brand-font-color-dark-lightened-30);
|
222
|
+
@if $use_high_contrast {
|
223
|
+
$ic-icon-link-color: lighten($ic-font-color-dark, 12%);
|
224
|
+
}
|
225
|
+
|
226
|
+
// linkColor is a deprecated Bootstrap 2 variable
|
227
|
+
$linkColor: var(--ic-link-color); // deprecated - do not use
|
228
|
+
$linkColorHover: var(--ic-link-color-darkened-10); // deprecated - do not use
|
229
|
+
|
230
|
+
//=====================
|
231
|
+
// Course Nav Variables
|
232
|
+
//=====================
|
233
|
+
// These variables control the active and hover
|
234
|
+
// states we have on the global left-hand sidenav in Canvas
|
235
|
+
$ic-course-sidenav_list-item--bg-color: $ic-color-light;
|
236
|
+
@if $use_high_contrast {
|
237
|
+
$ic-course-sidenav_list-item--bg-color: $ic-color-dark;
|
238
|
+
}
|
239
|
+
$ic-course-sidenav_list-item--active-font-color: var(--ic-brand-primary);
|
240
|
+
@if $use_high_contrast {
|
241
|
+
$ic-course-sidenav_list-item--active-font-color: $ic-color-light;
|
242
|
+
}
|
243
|
+
$ic-course-sidenav_list-item--inactive-font-color: darken($ic-color-neutral, 12);
|
244
|
+
|
245
|
+
//===============
|
246
|
+
// Icon Variables
|
247
|
+
//===============
|
248
|
+
//To be used for any disabled icon states
|
249
|
+
$ic-color-icon-disabled: darken($ic-color-neutral, 40);
|
250
|
+
@if $use_high_contrast {
|
251
|
+
$ic-color-icon-disabled: darken($ic-color-neutral, 60);
|
252
|
+
}
|
253
|
+
$ic-dim-helper-text: darken($ic-color-neutral, 45);
|
254
|
+
@if $use_high_contrast {
|
255
|
+
$ic-dim-helper-text: darken($ic-color-neutral, 55);
|
256
|
+
}
|
257
|
+
|
258
|
+
//==========================================================
|
259
|
+
// Legacy Vendor Variables (please do not touch these files)
|
260
|
+
//==========================================================
|
261
|
+
// We will be phasing these out
|
262
|
+
@import 'vendor/bootstrap/variables';
|
263
|
+
@import 'vendor/jqueryui/variables';
|
264
|
+
|
265
|
+
//==============================
|
266
|
+
// Legacy Global Color Variables - DO NOT USE
|
267
|
+
//==============================
|
268
|
+
// These variables we have reworked to use our canvas color variables for the
|
269
|
+
// new UI, however they will need to be evaluated on a case-by-case basis of
|
270
|
+
// their use in Canvas in order to properly phase them out
|
271
|
+
// Nothing changes in the legacy UI.
|
272
|
+
|
273
|
+
$lightBackground: $ic-color-medium-light;
|
274
|
+
$wellBackground: $ic-color-light;
|
275
|
+
$altBG: $ic-bg-light-neutral;
|
276
|
+
$borderColor: $ic-border-light;
|
277
|
+
$activeBG: $ic-bg-light-primary;
|
278
|
+
|
279
|
+
//=====================
|
280
|
+
// Transition Variables
|
281
|
+
//=====================
|
282
|
+
// This is a pleasing transition that can be used when you need
|
283
|
+
// a transition timing function
|
284
|
+
$ic-transition: cubic-bezier(0,1,0.5,1);
|
285
|
+
|
286
|
+
//=======================
|
287
|
+
// Form-related variables
|
288
|
+
//=======================
|
289
|
+
$ic-horizontal-form-offset: $ic-sp*16;
|
290
|
+
$ic-label-line-height: 1.3;
|
291
|
+
$ic-radio-checkbox-left-offset: 22px;
|
292
|
+
|
293
|
+
|
294
|
+
// override bootstrap green buttons
|
295
|
+
$green: #34832b !default;
|
296
|
+
|
297
|
+
// override default opacity for disabled classes
|
298
|
+
$ic-opacity-disabled: 0.6
|
@@ -0,0 +1,374 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (C) 2015 - present Instructure, Inc.
|
5
|
+
#
|
6
|
+
# This file is part of Canvas.
|
7
|
+
#
|
8
|
+
# Canvas is free software: you can redistribute it and/or modify it under
|
9
|
+
# the terms of the GNU Affero General Public License as published by the Free
|
10
|
+
# Software Foundation, version 3 of the License.
|
11
|
+
#
|
12
|
+
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
13
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
14
|
+
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
15
|
+
# details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License along
|
18
|
+
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'pathname'
|
21
|
+
require 'yaml'
|
22
|
+
require 'open3'
|
23
|
+
|
24
|
+
module BrandableCSS
|
25
|
+
APP_ROOT = defined?(Rails) && Rails.root || Pathname.pwd
|
26
|
+
CONFIG = YAML.load_file(APP_ROOT.join('config/brandable_css.yml')).freeze
|
27
|
+
BRANDABLE_VARIABLES = JSON.parse(File.read(APP_ROOT.join(CONFIG['paths']['brandable_variables_json']))).freeze
|
28
|
+
MIGRATION_NAME = 'RegenerateBrandFilesBasedOnNewDefaults'.freeze
|
29
|
+
|
30
|
+
use_compressed = (defined?(Rails) && Rails.env.production?) || (ENV['RAILS_ENV'] == 'production')
|
31
|
+
SASS_STYLE = ENV['SASS_STYLE'] || ((use_compressed ? 'compressed' : 'nested')).freeze
|
32
|
+
|
33
|
+
VARIABLE_HUMAN_NAMES = {
|
34
|
+
"ic-brand-primary" => lambda { I18n.t("Primary Brand Color") },
|
35
|
+
"ic-brand-font-color-dark" => lambda { I18n.t("Main Text Color") },
|
36
|
+
"ic-brand-font-family" => lambda { I18n.t("Font Family") },
|
37
|
+
"ic-brand-font-size" => lambda { I18n.t("Font Size") },
|
38
|
+
"ic-brand-font-weight" => lambda { I18n.t("Font Weight") },
|
39
|
+
"ic-link-color" => lambda { I18n.t("Link Color") },
|
40
|
+
"ic-brand-button--primary-bgd" => lambda { I18n.t("Primary Button") },
|
41
|
+
"ic-brand-button--primary-text" => lambda { I18n.t("Primary Button Text") },
|
42
|
+
"ic-brand-button--secondary-bgd" => lambda { I18n.t("Secondary Button") },
|
43
|
+
"ic-brand-button--secondary-text" => lambda { I18n.t("Secondary Button Text") },
|
44
|
+
"ic-brand-global-nav-bgd" => lambda { I18n.t("Nav Background") },
|
45
|
+
"ic-brand-global-nav-ic-icon-svg-fill" => lambda { I18n.t("Nav Icon") },
|
46
|
+
"ic-brand-global-nav-ic-icon-svg-fill--active" => lambda { I18n.t("Nav Icon Active") },
|
47
|
+
"ic-brand-global-nav-menu-item__text-color" => lambda { I18n.t("Nav Text") },
|
48
|
+
"ic-brand-global-nav-menu-item__text-color--active" => lambda { I18n.t("Nav Text Active") },
|
49
|
+
"ic-brand-global-nav-avatar-border" => lambda { I18n.t("Nav Avatar Border") },
|
50
|
+
"ic-brand-global-nav-menu-item__badge-bgd" => lambda { I18n.t("Nav Badge") },
|
51
|
+
"ic-brand-global-nav-menu-item__badge-text" => lambda { I18n.t("Nav Badge Text") },
|
52
|
+
"ic-brand-global-nav-logo-bgd" => lambda { I18n.t("Nav Logo Background") },
|
53
|
+
"ic-brand-header-image" => lambda { I18n.t("Nav Logo") },
|
54
|
+
"ic-brand-mobile-global-nav-logo" => lambda { I18n.t("Responsive Global Nav Logo") },
|
55
|
+
"ic-brand-watermark" => lambda { I18n.t("Watermark") },
|
56
|
+
"ic-brand-watermark-opacity" => lambda { I18n.t("Watermark Opacity") },
|
57
|
+
"ic-brand-favicon" => lambda { I18n.t("Favicon") },
|
58
|
+
"ic-brand-apple-touch-icon" => lambda { I18n.t("Mobile Homescreen Icon") },
|
59
|
+
"ic-brand-msapplication-tile-color" => lambda { I18n.t("Windows Tile Color") },
|
60
|
+
"ic-brand-msapplication-tile-square" => lambda { I18n.t("Windows Tile: Square") },
|
61
|
+
"ic-brand-msapplication-tile-wide" => lambda { I18n.t("Windows Tile: Wide") },
|
62
|
+
"ic-brand-right-sidebar-logo" => lambda { I18n.t("Right Sidebar Logo") },
|
63
|
+
"ic-brand-Login-body-bgd-color" => lambda { I18n.t("Background Color") },
|
64
|
+
"ic-brand-Login-body-bgd-image" => lambda { I18n.t("Background Image") },
|
65
|
+
"ic-brand-Login-body-bgd-shadow-color" => lambda { I18n.t("Body Shadow") },
|
66
|
+
"ic-brand-Login-logo" => lambda { I18n.t("Login Logo") },
|
67
|
+
"ic-brand-Login-Content-bgd-color" => lambda { I18n.t("Top Box Background") },
|
68
|
+
"ic-brand-Login-Content-border-color" => lambda { I18n.t("Top Box Border") },
|
69
|
+
"ic-brand-Login-Content-inner-bgd" => lambda { I18n.t("Inner Box Background") },
|
70
|
+
"ic-brand-Login-Content-inner-border" => lambda { I18n.t("Inner Box Border") },
|
71
|
+
"ic-brand-Login-Content-inner-body-bgd" => lambda { I18n.t("Form Background") },
|
72
|
+
"ic-brand-Login-Content-inner-body-border" => lambda { I18n.t("Form Border") },
|
73
|
+
"ic-brand-Login-Content-label-text-color" => lambda { I18n.t("Login Label") },
|
74
|
+
"ic-brand-Login-Content-password-text-color" => lambda { I18n.t("Login Link Color") },
|
75
|
+
"ic-brand-Login-footer-link-color" => lambda { I18n.t("Login Footer Link") },
|
76
|
+
"ic-brand-Login-footer-link-color-hover" => lambda { I18n.t("Login Footer Link Hover") },
|
77
|
+
"ic-brand-Login-instructure-logo" => lambda { I18n.t("Login Instructure Logo") }
|
78
|
+
}.freeze
|
79
|
+
|
80
|
+
GROUP_NAMES = {
|
81
|
+
"global_branding" => lambda { I18n.t("Global Branding") },
|
82
|
+
"global_navigation" => lambda { I18n.t("Global Navigation") },
|
83
|
+
"watermarks" => lambda { I18n.t("Watermarks & Other Images") },
|
84
|
+
"login" => lambda { I18n.t("Login Screen") }
|
85
|
+
}.freeze
|
86
|
+
|
87
|
+
HELPER_TEXTS = {
|
88
|
+
"ic-brand-header-image" => lambda { I18n.t("Accepted formats: svg, png, jpg, gif") },
|
89
|
+
"ic-brand-mobile-global-nav-logo" => lambda { I18n.t("Appears at the top of the global navigation tray that opens on mobile sized screens. display height: 48px. Accepted formats: svg, png, jpg, gif") },
|
90
|
+
"ic-brand-watermark" => lambda { I18n.t("This image appears as a background watermark to your page. Accepted formats: png, svg, gif, jpeg") },
|
91
|
+
"ic-brand-watermark-opacity" => lambda { I18n.t("Specify the transparency of the watermark background image.") },
|
92
|
+
"ic-brand-favicon" => lambda { I18n.t("You can use a single 16x16, 32x32, 48x48 ico file.") },
|
93
|
+
"ic-brand-apple-touch-icon" => lambda { I18n.t("The shortcut icon for iOS/Android devices. 180x180 png") },
|
94
|
+
"ic-brand-msapplication-tile-square" => lambda { I18n.t("558x558 png, jpg, gif (1.8x the standard tile size, so it can be scaled up or down as needed)") },
|
95
|
+
"ic-brand-msapplication-tile-wide" => lambda { I18n.t("558x270 png, jpg, gif") },
|
96
|
+
"ic-brand-right-sidebar-logo" => lambda { I18n.t("A full-size logo that appears in the right sidebar on the Canvas dashboard. Ideal size is 360 x 140 pixels. Accepted formats: svg, png, jpeg, gif") },
|
97
|
+
"ic-brand-Login-body-bgd-shadow-color" => lambda { I18n.t("accepted formats: hex, rgba, rgb, hsl") }
|
98
|
+
}.freeze
|
99
|
+
|
100
|
+
class << self
|
101
|
+
def variables_map
|
102
|
+
@variables_map ||= BRANDABLE_VARIABLES.each_with_object({}) do |variable_group, memo|
|
103
|
+
variable_group['variables'].each { |variable| memo[variable['variable_name']] = variable }
|
104
|
+
end.freeze
|
105
|
+
end
|
106
|
+
|
107
|
+
def variables_map_with_image_urls
|
108
|
+
@variables_map_with_image_urls ||= variables_map.each_with_object({}) do |(key, config), memo|
|
109
|
+
if config['type'] == 'image'
|
110
|
+
memo[key] = config.merge('default' => ActionController::Base.helpers.image_url(config['default']))
|
111
|
+
else
|
112
|
+
memo[key] = config
|
113
|
+
end
|
114
|
+
end.freeze
|
115
|
+
end
|
116
|
+
|
117
|
+
def things_that_go_into_defaults_md5
|
118
|
+
variables_map.each_with_object({}) do |(variable_name, config), memo|
|
119
|
+
default = config['default']
|
120
|
+
if config['type'] == 'image'
|
121
|
+
# to make consistent md5s whether the cdn is enabled or not, don't include hostname in defaults
|
122
|
+
default = ActionController::Base.helpers.image_path(default, host: '')
|
123
|
+
end
|
124
|
+
memo[variable_name] = default
|
125
|
+
end.freeze
|
126
|
+
end
|
127
|
+
|
128
|
+
def migration_version
|
129
|
+
# ActiveRecord usually uses integer timestamps to generate migration versions but any integer
|
130
|
+
# will work, so we just use the result of stripping out the alphabetic characters from the md5
|
131
|
+
default_variables_md5_without_migration_check.gsub(/[a-z]/, '').to_i.freeze
|
132
|
+
end
|
133
|
+
|
134
|
+
def check_if_we_need_to_create_a_db_migration
|
135
|
+
path = ActiveRecord::Migrator.migrations_paths.first
|
136
|
+
args = [path]
|
137
|
+
args << ActiveRecord::SchemaMigration unless CANVAS_RAILS5_2
|
138
|
+
migrations = ActiveRecord::MigrationContext.new(*args).migrations
|
139
|
+
['predeploy', 'postdeploy'].each do |pre_or_post|
|
140
|
+
migration = migrations.find { |m| m.name == MIGRATION_NAME + pre_or_post.camelize }
|
141
|
+
# they can't have the same id, so we just add 1 to the postdeploy one
|
142
|
+
expected_version = (pre_or_post == 'predeploy') ? migration_version : (migration_version + 1)
|
143
|
+
raise BrandConfigWithOutCompileAssets if expected_version == 85663486644871658581990
|
144
|
+
raise DefaultMD5NotUpToDateError unless migration && migration.version == expected_version
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def skip_migration_check?
|
149
|
+
# our canvas_rspec build doesn't even run `yarn install` or `gulp rev` so since
|
150
|
+
# they are not expecting all the frontend assets to work, this check isn't useful
|
151
|
+
Rails.env.test? && !Rails.root.join('public', 'dist', 'rev-manifest.json').exist?
|
152
|
+
end
|
153
|
+
|
154
|
+
def default_variables_md5
|
155
|
+
@default_variables_md5 ||= begin
|
156
|
+
check_if_we_need_to_create_a_db_migration unless skip_migration_check?
|
157
|
+
default_variables_md5_without_migration_check
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def default_variables_md5_without_migration_check
|
162
|
+
Digest::MD5.hexdigest(things_that_go_into_defaults_md5.to_json).freeze
|
163
|
+
end
|
164
|
+
|
165
|
+
def handle_urls(value, config, css_urls)
|
166
|
+
return value unless config['type'] == 'image' && css_urls
|
167
|
+
"url('#{value}')" if value.present?
|
168
|
+
end
|
169
|
+
|
170
|
+
# gets the *effective* value for a brandable variable
|
171
|
+
def brand_variable_value(variable_name, active_brand_config=nil, config_map=variables_map, css_urls=false)
|
172
|
+
config = config_map[variable_name]
|
173
|
+
explicit_value = active_brand_config && active_brand_config.get_value(variable_name).presence
|
174
|
+
return handle_urls(explicit_value, config, css_urls) if explicit_value
|
175
|
+
default = config['default']
|
176
|
+
if default && default.starts_with?('$')
|
177
|
+
if css_urls
|
178
|
+
return "var(--#{default[1..-1]})"
|
179
|
+
else
|
180
|
+
return brand_variable_value(default[1..-1], active_brand_config, config_map, css_urls)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# while in our sass, we want `url(/images/foo.png)`,
|
185
|
+
# the Rails Asset Helpers expect us to not have the '/images/', eg: <%= image_tag('foo.png') %>
|
186
|
+
default = default.sub(/^\/images\//, '') if config['type'] == 'image'
|
187
|
+
handle_urls(default, config, css_urls)
|
188
|
+
end
|
189
|
+
|
190
|
+
def computed_variables(active_brand_config=nil)
|
191
|
+
[
|
192
|
+
['ic-brand-primary', 'darken', 5],
|
193
|
+
['ic-brand-primary', 'darken', 10],
|
194
|
+
['ic-brand-primary', 'darken', 15],
|
195
|
+
['ic-brand-primary', 'lighten', 5],
|
196
|
+
['ic-brand-primary', 'lighten', 10],
|
197
|
+
['ic-brand-primary', 'lighten', 15],
|
198
|
+
['ic-brand-button--primary-bgd', 'darken', 5],
|
199
|
+
['ic-brand-button--primary-bgd', 'darken', 15],
|
200
|
+
['ic-brand-button--secondary-bgd', 'darken', 5],
|
201
|
+
['ic-brand-button--secondary-bgd', 'darken', 15],
|
202
|
+
['ic-brand-font-color-dark', 'lighten', 15],
|
203
|
+
['ic-brand-font-color-dark', 'lighten', 30],
|
204
|
+
['ic-link-color', 'darken', 10],
|
205
|
+
['ic-link-color', 'lighten', 10],
|
206
|
+
].each_with_object({}) do |(variable_name, darken_or_lighten, percent), memo|
|
207
|
+
color = brand_variable_value(variable_name, active_brand_config, variables_map_with_image_urls)
|
208
|
+
computed_color = CanvasColor::Color.new(color).send(darken_or_lighten, percent/100.0)
|
209
|
+
memo["#{variable_name}-#{darken_or_lighten}ed-#{percent}"] = computed_color.to_s
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def all_brand_variable_values(active_brand_config=nil, css_urls=false)
|
214
|
+
variables_map.each_with_object(computed_variables(active_brand_config)) do |(key, _), memo|
|
215
|
+
memo[key] = brand_variable_value(key, active_brand_config, variables_map_with_image_urls, css_urls)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def all_brand_variable_values_as_json(active_brand_config=nil)
|
220
|
+
all_brand_variable_values(active_brand_config).to_json
|
221
|
+
end
|
222
|
+
|
223
|
+
def all_brand_variable_values_as_js(active_brand_config=nil)
|
224
|
+
"CANVAS_ACTIVE_BRAND_VARIABLES = #{all_brand_variable_values_as_json(active_brand_config)};"
|
225
|
+
end
|
226
|
+
|
227
|
+
def all_brand_variable_values_as_css(active_brand_config=nil)
|
228
|
+
":root {
|
229
|
+
#{all_brand_variable_values(active_brand_config, true).map{ |k, v| "--#{k}: #{v};"}.join("\n")}
|
230
|
+
}"
|
231
|
+
end
|
232
|
+
|
233
|
+
def public_brandable_css_folder
|
234
|
+
Pathname.new('public/dist/brandable_css')
|
235
|
+
end
|
236
|
+
|
237
|
+
def default_brand_folder
|
238
|
+
public_brandable_css_folder.join('default')
|
239
|
+
end
|
240
|
+
|
241
|
+
def default_brand_file(type, high_contrast=false)
|
242
|
+
default_brand_folder.join("variables#{high_contrast ? '-high_contrast' : ''}-#{default_variables_md5}.#{type}")
|
243
|
+
end
|
244
|
+
|
245
|
+
def high_contrast_overrides
|
246
|
+
Class.new do
|
247
|
+
def get_value(variable_name)
|
248
|
+
{"ic-brand-primary" => "#0770A3", "ic-link-color" => "#0073A7"}[variable_name]
|
249
|
+
end
|
250
|
+
end.new
|
251
|
+
end
|
252
|
+
|
253
|
+
def default(type, high_contrast=false)
|
254
|
+
bc = high_contrast ? high_contrast_overrides : nil
|
255
|
+
send("all_brand_variable_values_as_#{type}", bc)
|
256
|
+
end
|
257
|
+
|
258
|
+
def save_default!(type, high_contrast=false)
|
259
|
+
default_brand_folder.mkpath
|
260
|
+
default_brand_file(type, high_contrast).write(default(type, high_contrast))
|
261
|
+
move_default_to_s3_if_enabled!(type, high_contrast)
|
262
|
+
end
|
263
|
+
|
264
|
+
def save_default_files!
|
265
|
+
[true, false].each do |high_contrast|
|
266
|
+
['js', 'css', 'json'].each { |type| save_default!(type, high_contrast) }
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
def move_default_to_s3_if_enabled!(type, high_contrast=false)
|
271
|
+
return unless defined?(Canvas) && Canvas::Cdn.enabled?
|
272
|
+
s3_uploader.upload_file(public_default_path(type, high_contrast))
|
273
|
+
begin
|
274
|
+
File.delete(default_brand_file(type, high_contrast))
|
275
|
+
rescue Errno::ENOENT # continue if something else deleted it in another process
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def s3_uploader
|
280
|
+
@s3_uploaderer ||= Canvas::Cdn::S3Uploader.new
|
281
|
+
end
|
282
|
+
|
283
|
+
def public_default_path(type, high_contrast=false)
|
284
|
+
"dist/brandable_css/default/variables#{high_contrast ? '-high_contrast' : ''}-#{default_variables_md5}.#{type}"
|
285
|
+
end
|
286
|
+
|
287
|
+
def variants
|
288
|
+
@variants ||= CONFIG['variants'].keys.freeze
|
289
|
+
end
|
290
|
+
|
291
|
+
def brandable_variants
|
292
|
+
@brandable_variants ||= CONFIG['variants'].select{|_, v| v['brandable']}.map{ |k,_| k }.freeze
|
293
|
+
end
|
294
|
+
|
295
|
+
def combined_checksums
|
296
|
+
if defined?(ActionController) && ActionController::Base.perform_caching && defined?(@combined_checksums)
|
297
|
+
return @combined_checksums
|
298
|
+
end
|
299
|
+
file = APP_ROOT.join(CONFIG['paths']['bundles_with_deps'] + SASS_STYLE)
|
300
|
+
if file.exist?
|
301
|
+
@combined_checksums = JSON.parse(file.read).each_with_object({}) do |(k, v), memo|
|
302
|
+
memo[k] = v.symbolize_keys.slice(:combinedChecksum, :includesNoVariables)
|
303
|
+
end.freeze
|
304
|
+
elsif defined?(Rails) && Rails.env.production?
|
305
|
+
raise "#{file.expand_path} does not exist. You need to run brandable_css before you can serve css."
|
306
|
+
else
|
307
|
+
# for dev/test there might be cases where you don't want it to raise an exception
|
308
|
+
# if you haven't ran `brandable_css` and the manifest file doesn't exist yet.
|
309
|
+
# eg: you want to test a controller action and you don't care that it links
|
310
|
+
# to a css file that hasn't been created yet.
|
311
|
+
default_value = {:combinedChecksum => "Error: unknown css checksum. you need to run brandable_css"}.freeze
|
312
|
+
@combined_checksums = Hash.new(default_value).freeze
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
# bundle path should be something like "bundles/speedgrader" or "plugins/analytics/something"
|
317
|
+
def cache_for(bundle_path, variant)
|
318
|
+
key = ["#{bundle_path}.scss", variant].join(CONFIG['manifest_key_seperator'])
|
319
|
+
fingerprint = combined_checksums[key]
|
320
|
+
raise "Fingerprint not found. #{bundle_path} #{variant}" unless fingerprint
|
321
|
+
fingerprint
|
322
|
+
end
|
323
|
+
|
324
|
+
def all_fingerprints_for(bundle_path)
|
325
|
+
variants.each_with_object({}) do |variant, object|
|
326
|
+
object[variant] = cache_for(bundle_path, variant)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
class BrandConfigWithOutCompileAssets < RuntimeError
|
332
|
+
def initialize
|
333
|
+
super <<-END
|
334
|
+
|
335
|
+
It looks like you are running a migration before running `rake canvas:compile_assets`
|
336
|
+
compile_assets needs to complete before running db:migrate if brand_configs have not run
|
337
|
+
|
338
|
+
run `rake canvas:compile_assets` and then try migrations again.
|
339
|
+
|
340
|
+
END
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
class DefaultMD5NotUpToDateError < RuntimeError
|
345
|
+
def initialize
|
346
|
+
super <<-END
|
347
|
+
|
348
|
+
Something has changed about the default variables or images used in the Theme Editor.
|
349
|
+
If you are seeing this and _you_ did not make changes to either app/stylesheets/brandable_variables.json
|
350
|
+
or one of the images it references, it probably meeans your local setup is out of date.
|
351
|
+
|
352
|
+
First, make sure you run `rake db:migrate`
|
353
|
+
and then run `./script/nuke_node.sh`
|
354
|
+
|
355
|
+
If that does not resolve the issue, it probably means you _did_ update one of those json variables
|
356
|
+
in app/stylesheets/brandable_variables.json or one of the images it references so you need to rename
|
357
|
+
the db migrations that makes sure when this change is deployed or checked out by anyone else
|
358
|
+
makes a new .css file for the css variables for each brand based on these new defaults.
|
359
|
+
To do that, run this command and then restart your rails process. (for local dev, if you want the
|
360
|
+
changes to show up in the ui, make sure you also run `rake db:migrate` afterwards).
|
361
|
+
|
362
|
+
ONLY DO THIS IF YOU REALLY DID MEAN TO MAKE A CHANGE TO THE DEFAULT BRANDING STUFF:
|
363
|
+
|
364
|
+
mv db/migrate/*_#{MIGRATION_NAME.underscore}_predeploy.rb \\
|
365
|
+
db/migrate/#{BrandableCSS.migration_version}_#{MIGRATION_NAME.underscore}_predeploy.rb \\
|
366
|
+
&& \\
|
367
|
+
mv db/migrate/*_#{MIGRATION_NAME.underscore}_postdeploy.rb \\
|
368
|
+
db/migrate/#{BrandableCSS.migration_version + 1}_#{MIGRATION_NAME.underscore}_postdeploy.rb
|
369
|
+
|
370
|
+
FYI, current variables are: #{BrandableCSS.things_that_go_into_defaults_md5}
|
371
|
+
END
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|