dsm-portfolio-theme 0.1.2 → 0.1.3
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/_includes/header.html +1 -0
- data/_includes/project-list.html +2 -2
- data/_includes/scripts.html +3 -0
- data/_layouts/default.html +3 -1
- data/_layouts/summary.html +3 -4
- data/_layouts/vignette.html +40 -1
- data/_sass/atoms/_typography.scss +0 -3
- data/_sass/organisms/_vignette-blocks.scss +9 -0
- data/_sass/organisms/_vignette-tabs.scss +11 -0
- data/assets/scripts/vignette.js +395 -0
- data/assets/styles/main.scss +2 -1
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af03e2322533472503d61bc2e70fd99a46205f32
|
4
|
+
data.tar.gz: 2727a309be069a06076b966ec71e85aa61f3eab8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c30ea9ec05632444bd9612272a1605cb356c132ae67d0ae78e71ee9ce86fede68eb2029c8b177a1813f136a1088ea28c948dce6608ff74ec026e5c2ac7328ea3
|
7
|
+
data.tar.gz: 5a7fc4184383677e60417574022105ab56bcf601700c0d17611193781738269f6baee57ba446b49f6d7052d6f314c32367716b120da80fec84661ea4a8f77e6c
|
data/_includes/header.html
CHANGED
data/_includes/project-list.html
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
</h2>
|
6
6
|
<div class="">
|
7
7
|
<!-- Group posts by subdirectory (parent project Id) -->
|
8
|
-
{% assign postsByProject = site.posts | group_by_exp: "post", "post.
|
8
|
+
{% assign postsByProject = site.posts | group_by_exp: "post", "post.project_id" %}
|
9
9
|
{% for project in postsByProject %}
|
10
10
|
<div class="">
|
11
11
|
<p class="">
|
@@ -15,7 +15,7 @@
|
|
15
15
|
<div class="">
|
16
16
|
<!-- Project details -->
|
17
17
|
<h3 class="">
|
18
|
-
{{ project.items[0].
|
18
|
+
{{ project.items[0].project_title }}
|
19
19
|
</h3>
|
20
20
|
<div class="">
|
21
21
|
{% for file in project.items %}
|
data/_layouts/default.html
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
|
11
11
|
<!-- Styles -->
|
12
12
|
<link rel="stylesheet" href="{{ "/assets/styles/main.css" | relative_url }}">
|
13
|
+
|
13
14
|
</head>
|
14
15
|
<body>
|
15
16
|
<!-- Header-->
|
@@ -21,6 +22,7 @@
|
|
21
22
|
<!-- Footer -->
|
22
23
|
{% include footer.html %}
|
23
24
|
|
24
|
-
<!--
|
25
|
+
<!-- Scripts -->
|
26
|
+
{% include scripts.html %}
|
25
27
|
</body>
|
26
28
|
</html>
|
data/_layouts/summary.html
CHANGED
@@ -4,12 +4,12 @@ layout: default
|
|
4
4
|
<div class="">
|
5
5
|
<div class="">
|
6
6
|
<a class="" href="{{ '/' | relative_url }}">Portfolio</a> >
|
7
|
-
{{ page.
|
7
|
+
{{ page.project_title }} >
|
8
8
|
{{ page.type | capitalize }}
|
9
9
|
</div>
|
10
10
|
<div class="">
|
11
11
|
<h1>
|
12
|
-
{{ page.
|
12
|
+
{{ page.project_title }}
|
13
13
|
</h1>
|
14
14
|
</div>
|
15
15
|
</div>
|
@@ -56,8 +56,7 @@ layout: default
|
|
56
56
|
</div>
|
57
57
|
{% if page.notebook_file %}
|
58
58
|
<div class="">
|
59
|
-
{%
|
60
|
-
{% jupyter_notebook notebook_path: notebook_path %}
|
59
|
+
{% jupyter_notebook site.notebook_base_path | append: page.notebook_file | relative_url %}
|
61
60
|
</div>
|
62
61
|
{% endif %}
|
63
62
|
</div>
|
data/_layouts/vignette.html
CHANGED
@@ -2,4 +2,43 @@
|
|
2
2
|
layout: default
|
3
3
|
---
|
4
4
|
|
5
|
-
|
5
|
+
<!-- Vignette tabs -->
|
6
|
+
<div class="o-vignette-tabs">
|
7
|
+
<h3>
|
8
|
+
Iterations
|
9
|
+
</h3>
|
10
|
+
<ul class="o-vignette-tabs__container">
|
11
|
+
{% for vignette in page.vignettes %}
|
12
|
+
{% if forloop.index == 1 %}
|
13
|
+
{% assign classString = 'o-vignette-tabs__tab--active' %}
|
14
|
+
{% else %}
|
15
|
+
{% assign classString = '' %}
|
16
|
+
{% endif %}
|
17
|
+
<li id="tab-{{ forloop.index | minus: 1 }}" class="o-vignette-tabs__tab {{ classString }}" onclick="javascript:$vignette.updateVignette({{ forloop.index | minus: 1 }})">
|
18
|
+
{{ forloop.index }}
|
19
|
+
</li>
|
20
|
+
{% endfor %}
|
21
|
+
</ul>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<!-- Competencies block -->
|
25
|
+
<div class="o-vignette-table">
|
26
|
+
<h3>
|
27
|
+
Competencies
|
28
|
+
</h3>
|
29
|
+
<table id="table">
|
30
|
+
<!-- Dynamically generated content -->
|
31
|
+
</table>
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<!-- Vignette content blocks -->
|
35
|
+
<div class="o-vignette-blocks">
|
36
|
+
{{ content }}
|
37
|
+
</div>
|
38
|
+
|
39
|
+
<!-- Inject data variables into page context for JavaScript -->
|
40
|
+
<script>
|
41
|
+
// Store raw data in ubiquitous object.
|
42
|
+
this.window['vignettes'] = {{ page.vignettes | jsonify }};
|
43
|
+
this.window['targets'] = {{ page.targets | jsonify }};
|
44
|
+
</script>
|
@@ -0,0 +1,395 @@
|
|
1
|
+
/**
|
2
|
+
* @
|
3
|
+
*/
|
4
|
+
$vignette = (function () {
|
5
|
+
// Set up variables.
|
6
|
+
|
7
|
+
// Data model
|
8
|
+
var _all = [];
|
9
|
+
var _vignettes = [];
|
10
|
+
var _targets = [];
|
11
|
+
var _diffs = [];
|
12
|
+
var _targetsHit = [];
|
13
|
+
var _index = 0;
|
14
|
+
var _tableData = [];
|
15
|
+
|
16
|
+
// UI elements
|
17
|
+
var _blocks = [];
|
18
|
+
var _tabs = [];
|
19
|
+
var _table = undefined;
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Initialize mini-library
|
23
|
+
* (bootstrap variables).
|
24
|
+
*
|
25
|
+
* @returns Exposed functions for UI to call
|
26
|
+
*/
|
27
|
+
function initialize() {
|
28
|
+
// Presume access to page variables.
|
29
|
+
_vignettes = window['vignettes'];
|
30
|
+
_targets = window['targets'];
|
31
|
+
|
32
|
+
// Defensive checking.
|
33
|
+
if(!_vignettes) {
|
34
|
+
throw "Necessary data not found in page";
|
35
|
+
return;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Compute all competencies.
|
39
|
+
_all = _combine();
|
40
|
+
|
41
|
+
for(var i = 0; i < _vignettes.length; i++) {
|
42
|
+
// Compute differences between vignettes ahead of time.
|
43
|
+
_diffs[i] = _diff(_vignettes[i - 1], _vignettes[i]);
|
44
|
+
// Compute targets hit per vignette ahead of time.
|
45
|
+
_targetsHit[i] = _target(_vignettes[i]);
|
46
|
+
// Compute table data ahead of time.
|
47
|
+
_tableData[i] = _tableify(i);
|
48
|
+
}
|
49
|
+
|
50
|
+
// Access DOM elements.
|
51
|
+
registerUI();
|
52
|
+
|
53
|
+
// Set table data.
|
54
|
+
_updateTable(0);
|
55
|
+
|
56
|
+
// Move to latest view.
|
57
|
+
_updateVignette(_vignettes.length - 1);
|
58
|
+
|
59
|
+
// Expose functions.
|
60
|
+
return {
|
61
|
+
dump: _dump,
|
62
|
+
updateVignette: _updateVignette,
|
63
|
+
combine: _combine
|
64
|
+
};
|
65
|
+
}
|
66
|
+
|
67
|
+
/**
|
68
|
+
* Retrieve DOM elements
|
69
|
+
* for manipulation.
|
70
|
+
*/
|
71
|
+
function registerUI() {
|
72
|
+
for(var i = 0; i < vignettes.length; i++) {
|
73
|
+
// Get tab and content block elements.
|
74
|
+
_blocks.push(document.getElementById('block-' + i.toString()));
|
75
|
+
_tabs.push(document.getElementById('tab-' + i.toString()));
|
76
|
+
}
|
77
|
+
|
78
|
+
_table = document.getElementById('table');
|
79
|
+
}
|
80
|
+
|
81
|
+
// Define UI manipulation functions.
|
82
|
+
|
83
|
+
/**
|
84
|
+
*
|
85
|
+
*
|
86
|
+
* @param {*} index
|
87
|
+
* @returns
|
88
|
+
*/
|
89
|
+
function _updateVignette(index) {
|
90
|
+
// Redundancy check.
|
91
|
+
if(_index === index) {
|
92
|
+
return;
|
93
|
+
}
|
94
|
+
|
95
|
+
// Update previous tab element.
|
96
|
+
_tabs[_index].classList.remove('o-vignette-tabs__tab--active');
|
97
|
+
|
98
|
+
// Update previous block element.
|
99
|
+
_blocks[_index].classList.remove('o-vignette-blocks__block--active');
|
100
|
+
|
101
|
+
// Update data model.
|
102
|
+
_index = index;
|
103
|
+
|
104
|
+
// Update tab element.
|
105
|
+
_tabs[_index].classList.add('o-vignette-tabs__tab--active');
|
106
|
+
|
107
|
+
// Update block element.
|
108
|
+
_blocks[_index].classList.add('o-vignette-blocks__block--active');
|
109
|
+
|
110
|
+
// Update competency table.
|
111
|
+
_updateTable(index);
|
112
|
+
}
|
113
|
+
|
114
|
+
/**
|
115
|
+
* Update the skill table based
|
116
|
+
* on the current vignette.
|
117
|
+
*
|
118
|
+
* @param {*} index The index of the current vignette.
|
119
|
+
*/
|
120
|
+
function _updateTable(index) {
|
121
|
+
// Remove previous rows (if any).
|
122
|
+
_clearTable(_table);
|
123
|
+
|
124
|
+
_table.innerHTML = _tableData[index];
|
125
|
+
}
|
126
|
+
|
127
|
+
// Define utility functions.
|
128
|
+
|
129
|
+
/**
|
130
|
+
* Output all notable variables.
|
131
|
+
*
|
132
|
+
* @returns An object containing variable contents
|
133
|
+
*/
|
134
|
+
function _dump(index) {
|
135
|
+
if(index) {
|
136
|
+
return {
|
137
|
+
vignette: _vignettes[index],
|
138
|
+
targets: _targets,
|
139
|
+
diff: _diffs[index],
|
140
|
+
targetsHit: _targetsHit[index]
|
141
|
+
};
|
142
|
+
} else {
|
143
|
+
return {
|
144
|
+
vignettes: _vignettes,
|
145
|
+
targets: _targets,
|
146
|
+
diffs: _diffs,
|
147
|
+
targetsHit: _targetsHit
|
148
|
+
};
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
function _tableify(index) {
|
153
|
+
// Build HTML for all unique skills...
|
154
|
+
var tableRowsHTML = [];
|
155
|
+
|
156
|
+
for(let competency of _all) {
|
157
|
+
// Build table row data.
|
158
|
+
var tableRowData = {
|
159
|
+
competencyId: competency,
|
160
|
+
target: _targets.indexOf(competency) != -1,
|
161
|
+
count: (total => {
|
162
|
+
for(let c of _vignettes[index]['competencies']) {
|
163
|
+
if(c['id'] === competency) {
|
164
|
+
return c['count'];
|
165
|
+
}
|
166
|
+
}
|
167
|
+
return 0;
|
168
|
+
})(),
|
169
|
+
removed: _indexDiffWithType(competency, index, 'removed'),
|
170
|
+
unchanged: _indexDiffWithType(competency, index, 'unchanged'),
|
171
|
+
added: _indexDiffWithType(competency, index, 'added')
|
172
|
+
};
|
173
|
+
// Convert table row data into HTML.
|
174
|
+
tableRowsHTML.push(_tableRowDataToHTML(tableRowData));
|
175
|
+
}
|
176
|
+
|
177
|
+
// Create new table.
|
178
|
+
var headerRow = '<tr id="table-header"><th>Competency</th>';
|
179
|
+
if(_targets) {
|
180
|
+
headerRow += '<th>Target</th>'
|
181
|
+
}
|
182
|
+
headerRow += '<th>Count</th><th>Removed</th><th>Unchanged</th><th>Added</th></tr>';
|
183
|
+
|
184
|
+
var finalHTML = headerRow;
|
185
|
+
for(let row of tableRowsHTML) {
|
186
|
+
finalHTML += row;
|
187
|
+
}
|
188
|
+
|
189
|
+
return finalHTML;
|
190
|
+
}
|
191
|
+
|
192
|
+
/**
|
193
|
+
* Shortcut method to get count of a competency
|
194
|
+
* within a category of change (if existent).
|
195
|
+
*
|
196
|
+
* @param {*} competency The competency Id
|
197
|
+
* @param {*} index The vignette iteration
|
198
|
+
* @param {*} type The type of change
|
199
|
+
* @returns The total occurences
|
200
|
+
*/
|
201
|
+
function _indexDiffWithType(competency, index, type) {
|
202
|
+
for(let c of _diffs[index][type]) {
|
203
|
+
if(c['id'] === competency) {
|
204
|
+
return c['countChange'];
|
205
|
+
}
|
206
|
+
}
|
207
|
+
return 0;
|
208
|
+
}
|
209
|
+
|
210
|
+
/**
|
211
|
+
* Convert table row data to raw HTML.
|
212
|
+
*
|
213
|
+
* @param {*} tableRowData HTML to inject.
|
214
|
+
*/
|
215
|
+
function _tableRowDataToHTML(tableRowData) {
|
216
|
+
var encoded = '<tr><td><span class="a-pill">' +
|
217
|
+
tableRowData['competencyId'] +
|
218
|
+
'</span></td><td>';
|
219
|
+
if(_targets) {
|
220
|
+
if(tableRowData['target']) {
|
221
|
+
encoded += 'Yes';
|
222
|
+
} else {
|
223
|
+
encoded += 'No';
|
224
|
+
}
|
225
|
+
encoded += '</td><td>';
|
226
|
+
}
|
227
|
+
encoded += tableRowData['count'] +
|
228
|
+
'</td><td>' +
|
229
|
+
tableRowData['removed'] +
|
230
|
+
'</td><td>' +
|
231
|
+
tableRowData['unchanged'] +
|
232
|
+
'</td><td>' +
|
233
|
+
tableRowData['added'] +
|
234
|
+
'</td></tr>';
|
235
|
+
return encoded;
|
236
|
+
}
|
237
|
+
|
238
|
+
/**
|
239
|
+
* Remove contents of table.
|
240
|
+
*
|
241
|
+
* @param {*} table The table DOM element
|
242
|
+
*/
|
243
|
+
function _clearTable(table) {
|
244
|
+
table.innerHTML = '';
|
245
|
+
}
|
246
|
+
|
247
|
+
/**
|
248
|
+
* Return an array of all competencies
|
249
|
+
* mentioned in any vignette or targets.
|
250
|
+
*
|
251
|
+
* @returns Array of unique competency Ids
|
252
|
+
*/
|
253
|
+
function _combine() {
|
254
|
+
allCompetencies = []
|
255
|
+
|
256
|
+
// Add all from vignettes.
|
257
|
+
for(let vignette of _vignettes) {
|
258
|
+
for(let competency of vignette['competencies']) {
|
259
|
+
allCompetencies.push(competency['id']);
|
260
|
+
}
|
261
|
+
}
|
262
|
+
|
263
|
+
// Add all from targets.
|
264
|
+
allCompetencies = allCompetencies.concat(_targets);
|
265
|
+
|
266
|
+
// De-duplicate.
|
267
|
+
return _uniqueBy(allCompetencies, k => k);
|
268
|
+
}
|
269
|
+
|
270
|
+
/**
|
271
|
+
* Compare differences in competencies reported in vignettes.
|
272
|
+
*
|
273
|
+
* @param {*} v1 Previous vignette
|
274
|
+
* @param {*} v2 New vignette
|
275
|
+
* @returns An object containing change information
|
276
|
+
*/
|
277
|
+
function _diff(v1, v2) {
|
278
|
+
// Hoist output declarations.
|
279
|
+
var differences = [], removed = [], unchanged = [], added = [];
|
280
|
+
|
281
|
+
// If it is the first vignette...
|
282
|
+
if(!v1) {
|
283
|
+
// All competencies are added, so get a list of them.
|
284
|
+
for(let competency of v2['competencies']) {
|
285
|
+
var c = { 'id': competency['id'], 'countChange': competency['count'] };
|
286
|
+
differences.push(c);
|
287
|
+
added.push(c);
|
288
|
+
}
|
289
|
+
} else {
|
290
|
+
// Create an index of all competencies in both vignettes.
|
291
|
+
differences = _uniqueBy(
|
292
|
+
v1['competencies'].concat(v2['competencies']),
|
293
|
+
k => k['id']
|
294
|
+
).map(c => {
|
295
|
+
return { 'id': c['id'], 'countChange': 0 };
|
296
|
+
});
|
297
|
+
|
298
|
+
// For every competency, check its state before and after.
|
299
|
+
for(let competency of differences) {
|
300
|
+
// Find out how many were in the both vignettes.
|
301
|
+
var numInV1 = 0, numInV2 = 0;
|
302
|
+
|
303
|
+
for(let c1 of v1['competencies']) {
|
304
|
+
if(c1['id'] === competency['id']) {
|
305
|
+
numInV1 = c1['count'];
|
306
|
+
break;
|
307
|
+
}
|
308
|
+
}
|
309
|
+
|
310
|
+
for(let c2 of v2['competencies']) {
|
311
|
+
if(c2['id'] === competency['id']) {
|
312
|
+
numInV2 = c2['count'];
|
313
|
+
break;
|
314
|
+
}
|
315
|
+
}
|
316
|
+
|
317
|
+
// Compute the change.
|
318
|
+
competency['countChange'] = numInV2 - numInV1;
|
319
|
+
}
|
320
|
+
|
321
|
+
// Perform extra formatting for view.
|
322
|
+
for(let competency of differences) {
|
323
|
+
if(competency['countChange'] < 0) {
|
324
|
+
removed.push(competency);
|
325
|
+
} else if(competency['countChange'] > 0) {
|
326
|
+
added.push(competency);
|
327
|
+
} else {
|
328
|
+
unchanged.push(competency);
|
329
|
+
}
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
return {
|
334
|
+
differences: differences,
|
335
|
+
removed: removed,
|
336
|
+
unchanged: unchanged,
|
337
|
+
added: added
|
338
|
+
};
|
339
|
+
}
|
340
|
+
|
341
|
+
/**
|
342
|
+
* Find which target Ids have been
|
343
|
+
* included in a vignette.
|
344
|
+
*
|
345
|
+
* @param {*} vignette The vignette to check
|
346
|
+
* @returns Targets that have been hit
|
347
|
+
*/
|
348
|
+
function _target(vignette) {
|
349
|
+
// Defensive sanity check.
|
350
|
+
if(!_targets) {
|
351
|
+
console.log('No targets defined for this project.');
|
352
|
+
return;
|
353
|
+
}
|
354
|
+
|
355
|
+
targetsHit = [];
|
356
|
+
|
357
|
+
// For every target Id...
|
358
|
+
for(let target of _targets) {
|
359
|
+
// Construct the outcome.
|
360
|
+
var outcome = {
|
361
|
+
'id': target,
|
362
|
+
'hit': false
|
363
|
+
};
|
364
|
+
|
365
|
+
// Search for it in the vignette.
|
366
|
+
for(let competency of vignette['competencies']) {
|
367
|
+
outcome['hit'] |= target === competency['id'];
|
368
|
+
if(outcome['hit']) {
|
369
|
+
break;
|
370
|
+
}
|
371
|
+
}
|
372
|
+
|
373
|
+
targetsHit.push(outcome);
|
374
|
+
}
|
375
|
+
|
376
|
+
return targetsHit;
|
377
|
+
}
|
378
|
+
|
379
|
+
/**
|
380
|
+
* De-duplicate an array by an object property.
|
381
|
+
*
|
382
|
+
* @param {*} a Array
|
383
|
+
* @param {*} key Callback returning object property
|
384
|
+
* @returns De-duplicated array
|
385
|
+
*/
|
386
|
+
function _uniqueBy(a, key) {
|
387
|
+
var seen = {};
|
388
|
+
return a.filter(function(item) {
|
389
|
+
var k = key(item);
|
390
|
+
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
|
391
|
+
})
|
392
|
+
}
|
393
|
+
|
394
|
+
return initialize();
|
395
|
+
})();
|
data/assets/styles/main.scss
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dsm-portfolio-theme
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Hills
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.0.
|
33
|
+
version: 0.0.4
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.0.
|
40
|
+
version: 0.0.4
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -79,6 +79,7 @@ files:
|
|
79
79
|
- _includes/footer.html
|
80
80
|
- _includes/header.html
|
81
81
|
- _includes/project-list.html
|
82
|
+
- _includes/scripts.html
|
82
83
|
- _layouts/default.html
|
83
84
|
- _layouts/page.html
|
84
85
|
- _layouts/portfolio.html
|
@@ -101,7 +102,10 @@ files:
|
|
101
102
|
- _sass/layouts/_portfolio.scss
|
102
103
|
- _sass/molecules/_footer.scss
|
103
104
|
- _sass/molecules/_header.scss
|
105
|
+
- _sass/organisms/_vignette-blocks.scss
|
106
|
+
- _sass/organisms/_vignette-tabs.scss
|
104
107
|
- assets/notebooks/demo.ipynb
|
108
|
+
- assets/scripts/vignette.js
|
105
109
|
- assets/styles/main.scss
|
106
110
|
homepage: https://github.com/joshhills/dsm-portfolio/theme
|
107
111
|
licenses:
|