Integrated scss style building in Grunt extension

This commit is contained in:
PMKuipers 2023-08-26 23:37:36 +02:00
parent 413f5c3e4f
commit 64f9b8b043
9 changed files with 2299 additions and 793 deletions

101
Gruntfile.js Normal file
View File

@ -0,0 +1,101 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle 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 3 of the License, or
// (at your option) any later version.
//
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* Grunt configuration for local_treestudyplan
*
* @copyright 2023 P.M. Kuipers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Grunt configuration.
*
* @param {Grunt} grunt
*/
module.exports = function(grunt) {
const path = require('path');
const process = require('process');
const sass = require('sass');
// Import grunt configuration for moodle base
process.chdir("../.."); // change dir to moodle base
require(path.resolve(`./Gruntfile.js`))(grunt); // Run Gruntfile module from moodle base
grunt.registerTask('scssplugin','Compile scss/*.sccs into styles.css and css/devstyles.css', () => {
const devoutput = 'css/devstyles.css';
const prodoutput = 'styles.css';
// Get full path of compenent and scss folder
const componentPath = path.join(grunt.moodleEnv.gruntFilePath,grunt.moodleEnv.componentDirectory);
const scssPath = path.join(componentPath, 'scss','styles.scss');
console.log(`Compiling ${scssPath} including any imported files therein`);
process.chdir(path.join(componentPath, 'scss'));
const result = sass.compile(scssPath);
if ( result ) {
console.info("got result");
// Some regex processing to match moodle stylelint styles
// change tab indent to 4 instead of 2
let css = result.css.replace(/^ ([^ ])/gm ," $1");
// insert a newline after every comma in a css selector
// (only combined selectors will get that long)
css = css.replace(/^[^ ].*[\{,]$/gm , (m) => { // Find CSS selector lines
return m.replace(/, /g,",\n"); // replace comma followed by space with comma newline
});
// replace hex color codes with lowercase (convenience function since I don't really care for the hex codes lowercase only rule)
const hexCodeToLower = (match, m1, m2) => {
return '#'+m1.toLowerCase()+m2;
}
css = css.replace(/#([A-F0-9a-f]{3})([^A-F0-9a-f]?)/gm , hexCodeToLower); // 3 digit color codes
css = css.replace(/#([A-F0-9a-f]{6})([^A-F0-9a-f]?)/gm , hexCodeToLower); // 6 digit color codes
css = css.replace(/#([A-F0-9a-f]{8})([^A-F0-9a-f]?)/gm , hexCodeToLower); // 8 digit color codes (with alpha)
// All other errors should really be fixed in the scss files :)
[devoutput,prodoutput].forEach((output) => {
console.info(`Storing ${output}`);
grunt.file.write(path.join(componentPath, output),css);
});
}
});
// Rebuild on changes in the scss files when using 'grunt watch'
grunt.config.merge({
watch: {
scssplugin: {
files: ['scss/*.scss'],
tasks: ['scssplugin']
},
},
});
// Remove gherkinlint from the startup list, since it exits with an error because of errors in moodle's own code
grunt.moodleEnv.startupTasks.splice(grunt.moodleEnv.startupTasks.indexOf("gherkinlint"),1);
// Add the 'scssplugin' task as a startup task.
grunt.moodleEnv.startupTasks.push('scssplugin');
};

View File

@ -14,6 +14,7 @@ $SCRIPTDIR/vuemode.sh prod
# so we can be sure all javascript is properly built from the most recent source # so we can be sure all javascript is properly built from the most recent source
cd $SCRIPTDIR cd $SCRIPTDIR
grunt amd grunt amd
grunt scssplugin # plugin specific scss task to compile styles.css from scss files
# run the build php script # run the build php script
php ${SCRIPTDIR}/build.php $@ php ${SCRIPTDIR}/build.php $@

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
.path-local-treestudyplan { .path-local-treestudyplan {
div.tab-pane:target { div.tab-pane:target {
margin-top: 0px; margin-top: 0;
} }
[v-cloak] { [v-cloak] {
@ -12,4 +12,8 @@
margin: auto; margin: auto;
} }
.special {
color: gold;
}
} }

View File

@ -5,16 +5,16 @@ quite hard to maintain.
Unfortunately, moodle does not extend the sass/scss compiler support to plugins Unfortunately, moodle does not extend the sass/scss compiler support to plugins
that are not a theme. that are not a theme.
To alleviate this, this plugin includes it's own scss compiler script that compiles To alleviate this, this plugin extends moodle's Gruntfile.js scripts
all scss files in this directory into one css file - css/devstyles.css to compile 'scss/styles.scss' into 'css/devstyles.css' (and 'styles.css')
This files is used instead of styles.css in order to avoid having to clear the theme 'css/devstyles.css' is used instead of styles.css in order to avoid having to clear the theme
cache every time a style rule is changed during development. cache every time a style rule is changed during development.
Once I devise a method to use styles.css in production environtments and css/devstyles.css Once I devise a method to use styles.css in production environtments and css/devstyles.css
production environments, the compiler will compile it into both css/devstyles.css production environments, the compiler will compile it into both css/devstyles.css
and styles.css and styles.css
Call the plugin's scss compiler by running scssbuild.sh in the plugin's root. The grunt command to compile is 'grunt scssplugin'

View File

@ -71,7 +71,7 @@
display: grid; display: grid;
grid-auto-flow: column; grid-auto-flow: column;
/*border-bottom-style: solid;*/ /*border-bottom-style: solid;*/
border-color: #cccccc; border-color: #ccc;
border-width: 1px; border-width: 1px;
} }
@ -91,7 +91,7 @@
.t-studyline .t-studyline-editmode-content { .t-studyline .t-studyline-editmode-content {
border-right-style: solid; border-right-style: solid;
border-color: #cccccc; border-color: #ccc;
border-width: 1px; border-width: 1px;
} }
@ -233,19 +233,19 @@
.t-studyline-slot.t-studyline-slot-0 .t-slot-drop.filter .t-slot-item, .t-studyline-slot.t-studyline-slot-0 .t-slot-drop.filter .t-slot-item,
.r-studyline-slot.r-studyline-slot-0 .r-item-base { .r-studyline-slot.r-studyline-slot-0 .r-item-base {
margin-left: 0px; margin-left: 0;
} }
.t-studyline-slot.gradable.current.odd, .t-studyline-slot.gradable.current.odd,
.r-studyline-slot.gradable.current.odd { .r-studyline-slot.gradable.current.odd {
--hlcol: color-mix(in srgb, var(--less-light) , var(--highlight) var(--highlight-mix)); --hlcol: color-mix(in srgb, var(--less-light), var(--highlight) var(--highlight-mix));
background-color: var(--hlcol); background-color: var(--hlcol);
position: relative; position: relative;
} }
.t-studyline-slot.gradable.current.odd:before, .t-studyline-slot.gradable.current.odd:before,
.r-studyline-slot.gradable.current.odd:before { .r-studyline-slot.gradable.current.odd:before {
--hlcol: color-mix(in srgb, var(--less-light) , var(--highlight) var(--highlight-mix)); --hlcol: color-mix(in srgb, var(--less-light), var(--highlight) var(--highlight-mix));
box-shadow: -20px 0 10px -7px var(--hlcol) inset; box-shadow: -20px 0 10px -7px var(--hlcol) inset;
content: " "; content: " ";
height: 100%; height: 100%;
@ -257,7 +257,7 @@
.t-studyline-slot.gradable.current.odd:after, .t-studyline-slot.gradable.current.odd:after,
.r-studyline-slot.gradable.current.odd:after { .r-studyline-slot.gradable.current.odd:after {
--hlcol: color-mix(in srgb, var(--less-light) , var(--highlight) var(--highlight-mix)); --hlcol: color-mix(in srgb, var(--less-light), var(--highlight) var(--highlight-mix));
box-shadow: 20px 0 10px -7px var(--hlcol) inset; box-shadow: 20px 0 10px -7px var(--hlcol) inset;
content: " "; content: " ";
height: 100%; height: 100%;
@ -272,7 +272,7 @@
} }
.s-studyline-header-period.current { .s-studyline-header-period.current {
--hlcol: color-mix(in srgb, var(--white) , var(--highlight) var(--highlight-mix)); --hlcol: color-mix(in srgb, var(--white), var(--highlight) var(--highlight-mix));
box-shadow: 0 0 10px 10px var(--hlcol); box-shadow: 0 0 10px 10px var(--hlcol);
background-color: var(--hlcol); background-color: var(--hlcol);
border-top-left-radius: 16px; border-top-left-radius: 16px;
@ -285,14 +285,14 @@
.t-studyline-slot.gradable.current.even, .t-studyline-slot.gradable.current.even,
.r-studyline-slot.gradable.current.even { .r-studyline-slot.gradable.current.even {
--hlcol: color-mix(in srgb, var(--white) , var(--highlight) var(--highlight-mix)); --hlcol: color-mix(in srgb, var(--white), var(--highlight) var(--highlight-mix));
background-color: var(--hlcol); background-color: var(--hlcol);
position: relative; position: relative;
} }
.t-studyline-slot.gradable.current.even:before, .t-studyline-slot.gradable.current.even:before,
.r-studyline-slot.gradable.current.even:before { .r-studyline-slot.gradable.current.even:before {
--hlcol: color-mix(in srgb, var(--white) , var(--highlight) var(--highlight-mix)); --hlcol: color-mix(in srgb, var(--white), var(--highlight) var(--highlight-mix));
box-shadow: -20px 0 10px -7px var(--hlcol) inset; box-shadow: -20px 0 10px -7px var(--hlcol) inset;
content: " "; content: " ";
height: 100%; height: 100%;
@ -308,7 +308,7 @@
.t-studyline-slot.gradable.current.even:after, .t-studyline-slot.gradable.current.even:after,
.r-studyline-slot.gradable.current.even:after { .r-studyline-slot.gradable.current.even:after {
--hlcol: color-mix(in srgb, var(--white) , var(--highlight) var(--highlight-mix)); --hlcol: color-mix(in srgb, var(--white), var(--highlight) var(--highlight-mix));
box-shadow: 20px 0 10px -7px var(--hlcol) inset; box-shadow: 20px 0 10px -7px var(--hlcol) inset;
content: " "; content: " ";
height: 100%; height: 100%;
@ -361,7 +361,7 @@
.t-item-deletebox.drop-in { .t-item-deletebox.drop-in {
visibility: visible; visibility: visible;
border-style: solid; border-style: solid;
background-color: #FFCCCC; background-color: #FCC;
color: #a00; color: #a00;
} }
@ -401,7 +401,7 @@
position: absolute; position: absolute;
top: calc(50% - 5px); top: calc(50% - 5px);
right: -1px; right: -1px;
line-height: 0px; line-height: 0;
} }
.t-item-connector-start svg rect { .t-item-connector-start svg rect {
@ -421,7 +421,7 @@
top: 50%; top: 50%;
transform: translate(0, -50%); transform: translate(0, -50%);
left: -1px; left: -1px;
line-height: 0px; line-height: 0;
} }
.t-item-connector-end svg rect { .t-item-connector-end svg rect {
@ -458,7 +458,7 @@
position: absolute; position: absolute;
left: 50%; left: 50%;
transform: translate(-50%, 100%); transform: translate(-50%, 100%);
bottom: 0px; bottom: 0;
z-index: 25; z-index: 25;
} }
@ -474,7 +474,7 @@
.t-item-filter { .t-item-filter {
display: inline-block; display: inline-block;
height: 1em; height: 1em;
padding: 0px; padding: 0;
margin: 0; margin: 0;
text-align: left; text-align: left;
font-size: 2em; font-size: 2em;
@ -545,7 +545,7 @@
a.t-item-course-config { a.t-item-course-config {
font-size: 16pt; font-size: 21px /*16pt*/;
vertical-align: middle; vertical-align: middle;
float: right; float: right;
margin-right: 2px; margin-right: 2px;
@ -698,7 +698,7 @@
.r-item-filter { .r-item-filter {
display: inline-block; display: inline-block;
padding: 0px; padding: 0;
text-align: left; text-align: left;
font-size: 2em; font-size: 2em;
vertical-align: top; vertical-align: top;
@ -799,14 +799,14 @@
} }
.r-course-grading { .r-course-grading {
font-size: 16pt; font-size: 21px /*16pt*/;
margin-right: 2px; margin-right: 2px;
vertical-align: bottom; vertical-align: bottom;
} }
.r-course-graded, .r-course-graded,
.r-course-result { .r-course-result {
font-size: 16pt; font-size: 21px /*16pt*/;
vertical-align: middle; vertical-align: middle;
float: right; float: right;
margin-right: 2px; margin-right: 2px;
@ -819,7 +819,7 @@
} }
.r-completion-detail-header { .r-completion-detail-header {
font-size: 20pt; font-size: 26px /*20pt*/;
} }
.r-item-finish.completion-incomplete, .r-item-finish.completion-incomplete,
@ -1019,7 +1019,7 @@
} }
.s-studyplan-card-title-buttons { .s-studyplan-card-title-buttons {
font-size: 12pt; font-size: 16px /*12pt*/;
float: right; float: right;
} }
.s-studyplan-card-title-buttons > * { .s-studyplan-card-title-buttons > * {
@ -1115,9 +1115,14 @@
margin-right: 1em; margin-right: 1em;
} }
.s-edit-mod-form [data-fieldtype=submit] { display: none ! important; } .s-edit-mod-form [data-fieldtype=submit] {
.s-edit-mod-form.genericonly form > fieldset:not(#id_general) { display: none ! important; } /* if not working, make selector more specific */
display: none;
}
.s-edit-mod-form.genericonly form > fieldset:not(#id_general) {
/* if not working, make selector more specific */
display: none;
}
.border-grey { .border-grey {
border-color: #aaa; border-color: #aaa;
} }

4
scss/styles.scss Normal file
View File

@ -0,0 +1,4 @@
@import "colors.scss";
@import "generic.scss";
@import "invitemanager.scss";
@import "studyplan.scss"

View File

@ -1,63 +0,0 @@
#!/usr/bin/env node
// This file is part of the Studyplan plugin for Moodle
//
// Moodle 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 3 of the License, or
// (at your option) any later version.
//
// Moodle 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 Moodle. If not, see <https://www.gnu.org/licenses/>.
/**
* This file compiles the scss files in the scss/ folder into either the main
* styles.css for production upon build or css/devstyles.css for development
*
* Most nice would be to integrate this action with grunt watch, but I am
* not familiar enough with grunt to know if I can extend moodle's grunt actions
* from a Gruntfile.js in this directory without modifying Moodle's Gruntfile.js
*
* @package local_treestudyplan
* @copyright 2023 P.M. Kuipers
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
const sass = require('sass');
const path = require('path');
const fs = require('fs');
const output = 'css/devstyles.css';
let css = "";
let map = "";
//joining path of directory
const directoryPath = path.join(__dirname, 'scss');
//passsing directoryPath and callback function
fs.readdir(directoryPath, function (err, files) {
//handling error
if (err) {
return console.log('Unable to scan directory: ' + err);
}
//listing all files using forEach
files.forEach(function (file) {
if (file.endsWith(".scss")) {
const result = sass.compile(file);
console.info(`Processing ${file}...`)
if ( result ) {
css = css + `/**** ${file} ****/\n` + result.css + "\n";
}
}
});
console.info(`Storing ${output}`);
fs.writeFile(path.join(__dirname, output),css,(err) => {
if (err) throw err;
});
});

1274
styles.css

File diff suppressed because it is too large Load Diff