main: Stop importing patternfly.css

* Stop importing cockpit's base1/patternfly.css

This is deprecated API and will be dropped at some point, in favor
of projects shipping their own CSS.

Install and import the styles from PF4 now.

* Use webpack based string replacement for removing the font-face rules from PF4

Doing the seddery in Makefile breaks `npm run build`, webpack watching,
and is generally brittle.
Do the font replacement hacking with `string-replace-loader`, which fits into webpack much more nicely.

There is still some potential simplification by not duplicating the
entire scss loader chain.

Co-authored-by: Martin Pitt <martin@piware.de>

Closes #315
This commit is contained in:
Katerina Koukiou 2020-05-28 10:01:31 +02:00 committed by GitHub
parent 8adad16874
commit 96514e279e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 178 additions and 19 deletions

View file

@ -33,19 +33,22 @@
"eslint-plugin-react": "^7.14.3", "eslint-plugin-react": "^7.14.3",
"eslint-plugin-react-hooks": "^2.1.2", "eslint-plugin-react-hooks": "^2.1.2",
"eslint-plugin-standard": "^4.0.1", "eslint-plugin-standard": "^4.0.1",
"mini-css-extract-plugin": "^0.9.0",
"htmlparser": "^1.7.7", "htmlparser": "^1.7.7",
"jed": "^1.1.1", "jed": "^1.1.1",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "4.14.1",
"po2json": "^1.0.0-alpha", "po2json": "^1.0.0-alpha",
"sass-loader": "^7.0.3", "sass-loader": "^7.0.3",
"sizzle": "^2.3.3", "sizzle": "^2.3.3",
"stdio": "^0.2.7", "stdio": "^0.2.7",
"string-replace-loader": "^2.3.0",
"webpack": "^4.17.1", "webpack": "^4.17.1",
"webpack-cli": "^3.1.0" "webpack-cli": "^3.1.0"
}, },
"dependencies": { "dependencies": {
"@patternfly/patternfly": "^2.71.6",
"@patternfly/react-core": "^3.158.1",
"core-js": "3.6.5", "core-js": "3.6.5",
"node-sass": "4.14.1",
"react": "16.13.1", "react": "16.13.1",
"react-dom": "16.13.1" "react-dom": "16.13.1"
} }

View file

@ -19,6 +19,7 @@
import cockpit from 'cockpit'; import cockpit from 'cockpit';
import React from 'react'; import React from 'react';
import { Alert, Card, CardHead, CardHeader, CardHeadMain, Title } from '@patternfly/react-core';
import './app.scss'; import './app.scss';
const _ = cockpit.gettext; const _ = cockpit.gettext;
@ -35,12 +36,19 @@ export class Application extends React.Component {
render() { render() {
return ( return (
<div className="container-fluid"> <Card>
<h2>Starter Kit</h2> <CardHead>
<p> <CardHeadMain>
{ cockpit.format(_("Running on $0"), this.state.hostname) } <Title headingLevel="h2" size="3xl">Starter Kit</Title>
</p> </CardHeadMain>
</div> </CardHead>
<CardHeader>
<Alert
variant="default"
title={ cockpit.format(_("Running on $0"), this.state.hostname) }
/>
</CardHeader>
</Card>
); );
} }
} }

View file

@ -22,7 +22,6 @@ along with this package; If not, see <http://www.gnu.org/licenses/>.
<meta name="description" content=""> <meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../base1/patternfly.css">
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
<script type="text/javascript" src="../base1/cockpit.js"></script> <script type="text/javascript" src="../base1/cockpit.js"></script>
@ -30,7 +29,7 @@ along with this package; If not, see <http://www.gnu.org/licenses/>.
<script type="text/javascript" src="index.js"></script> <script type="text/javascript" src="index.js"></script>
</head> </head>
<body> <body class="pf-m-redhat-font">
<div id="app"></div> <div id="app"></div>
</body> </body>
</html> </html>

View file

@ -17,11 +17,21 @@
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>. * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
*/ */
import "./lib/patternfly-4-cockpit.scss";
import "core-js/stable"; import "core-js/stable";
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Application } from './app.jsx'; import { Application } from './app.jsx';
/*
* PF4 overrides need to come after the JSX components imports because
* these are importing CSS stylesheets that we are overriding
* Having the overrides here will ensure that when mini-css-extract-plugin will extract the CSS
* out of the dist/index.js and since it will maintain the order of the imported CSS,
* the overrides will be correctly in the end of our stylesheet.
*/
import "./lib/patternfly-4-overrides.scss";
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
ReactDOM.render(React.createElement(Application, {}), document.getElementById('app')); ReactDOM.render(React.createElement(Application, {}), document.getElementById('app'));

36
src/lib/_fonts.scss Normal file
View file

@ -0,0 +1,36 @@
/*
* Keep in sync with https://github.com/cockpit-project/cockpit/tree/master/src/base1/_fonts.scss
*/
@mixin printRedHatFont(
$weightValue: 400,
$weightName: "Regular",
$familyName: "RedHatText",
$style: "normal",
$relative: true
) {
$filePath: "../../static/fonts" + "/" + $familyName + "-" + $weightName;
@font-face {
font-family: $familyName;
src: url('#{$filePath}.woff2') format('woff2');
font-style: #{$style};
font-weight: $weightValue;
text-rendering: optimizeLegibility;
}
}
@include printRedHatFont(700, "Bold", $familyName: "RedHatDisplay");
@include printRedHatFont(700, "BoldItalic", $style: "italic", $familyName: "RedHatDisplay");
@include printRedHatFont(300, "Black", $familyName: "RedHatDisplay");
@include printRedHatFont(300, "BlackItalic", $style: "italic", $familyName: "RedHatDisplay");
@include printRedHatFont(300, "Italic", $style: "italic", $familyName: "RedHatDisplay");
@include printRedHatFont(400, "Medium", $familyName: "RedHatDisplay");
@include printRedHatFont(400, "MediumItalic", $style: "italic", $familyName: "RedHatDisplay");
@include printRedHatFont(300, "Regular", $familyName: "RedHatDisplay");
@include printRedHatFont(300, "Bold");
@include printRedHatFont(300, "BoldItalic", $style: "italic");
@include printRedHatFont(300, "Italic");
@include printRedHatFont(700, "Medium");
@include printRedHatFont(700, "MediumItalic", $style: "italic");
@include printRedHatFont(400, "Regular");

View file

@ -0,0 +1,14 @@
/*
* Keep in sync with https://github.com/cockpit-project/cockpit/tree/master/src/base1/patternfly-4-cockpit.scss
*/
/* Set fake font and icon path variables - we are going to indentify these through
* string replacement and remove the relevant font-face declarations
*/
$pf-global--font-path: 'patternfly-fonts-fake-path';
$pf-global--fonticon-path: 'patternfly-icons-fake-path';
$pf-global--disable-fontawesome: true !default; // Disable Font Awesome 5 Free
@import '@patternfly/patternfly/patternfly-base.scss';
/* Import our own fonts since the PF4 font-face rules are filtered out with patternfly.sed */
@import "./fonts";

View file

@ -0,0 +1,43 @@
/*
* Keep in sync with https://github.com/cockpit-project/cockpit/tree/master/pkg/lib/patternfly-4-overrides.scss
*/
/*** PF4 overrides ***/
/* WORKAROUND: Override word-break bug */
/* See: https://github.com/patternfly/patternfly-next/issues/2325 */
.pf-c-table td {
word-break: normal;
overflow-wrap: break-word;
}
/* WORKAROUND: Dropdown (PF4): Caret is not properly aligned bug */
/* See: https://github.com/patternfly/patternfly/issues/2715 */
/* Align the icons inside of all dropdown toggles. */
/* Part 1 of 2 */
.pf-c-dropdown__toggle-button {
display: flex;
align-items: center;
}
/* Make split button dropdowns the same height as their sibling. */
/* Part 2 of 2 */
.pf-m-split-button {
align-items: stretch;
}
/* WORKAROUND: Navigation problems with Tertiary Nav widget on mobile */
/* See: https://github.com/patternfly/patternfly-design/issues/840 */
/* Helper mod to wrap pf-c-nav__tertiary */
.ct-m-nav__tertiary-wrap {
flex-wrap: wrap;
.pf-c-nav__scroll-button {
display: none;
}
}
/* Helper mod to center pf-c-nav__tertiary when it wraps */
.ct-m-nav__tertiary-center {
justify-content: center;
}

View file

@ -20,16 +20,16 @@ class TestApplication(testlib.MachineCase):
self.login_and_go("/starter-kit") self.login_and_go("/starter-kit")
# verify expected heading # verify expected heading
b.wait_text(".container-fluid h2", "Starter Kit") b.wait_text("h2.pf-c-title", "Starter Kit")
# verify expected host name # verify expected host name
hostname = m.execute("hostname").strip() hostname = m.execute("hostname").strip()
b.wait_text(".container-fluid p", "Running on " + hostname) b.wait_in_text("h4.pf-c-alert__title", "Running on " + hostname)
# change current hostname # change current hostname
m.execute("echo new-%s > /etc/hostname" % hostname) m.execute("echo new-%s > /etc/hostname" % hostname)
# verify new hostname name # verify new hostname name
b.wait_text(".container-fluid p", "Running on new-" + hostname) b.wait_in_text("h4.pf-c-alert__title", "Running on new-" + hostname)
# change language to German # change language to German
b.switch_to_top() b.switch_to_top()
@ -48,7 +48,7 @@ class TestApplication(testlib.MachineCase):
b.go("/starter-kit") b.go("/starter-kit")
b.enter_page("/starter-kit") b.enter_page("/starter-kit")
# page label (from js) should be translated # page label (from js) should be translated
b.wait_in_text(".container-fluid p", "Läuft auf") b.wait_in_text("h4.pf-c-alert__title", "Läuft auf")
if __name__ == '__main__': if __name__ == '__main__':
testlib.test_main() testlib.test_main()

View file

@ -115,6 +115,9 @@ var babel_loader = {
module.exports = { module.exports = {
mode: production ? 'production' : 'development', mode: production ? 'production' : 'development',
resolve: {
modules: [ nodedir ],
},
entry: info.entries, entry: info.entries,
externals: externals, externals: externals,
output: output, output: output,
@ -132,20 +135,63 @@ module.exports = {
use: babel_loader, use: babel_loader,
test: /\.(js|jsx)$/ test: /\.(js|jsx)$/
}, },
/* HACK: remove unwanted fonts from PatternFly's css */
{ {
exclude: /node_modules/, test: /patternfly-4-cockpit.scss$/,
test: /\.scss$/,
use: [ use: [
extract.loader, extract.loader,
{ {
loader: 'css-loader', loader: 'css-loader',
options: { url: false } options: {
sourceMap: true,
url: false
}
},
{
loader: 'string-replace-loader',
options: {
multiple: [
{
search: /src:url\("patternfly-icons-fake-path\/pficon[^}]*/g,
replace: "src:url('fonts/patternfly.woff')format('woff');",
},
{
search: /@font-face[^}]*patternfly-fonts-fake-path[^}]*}/g,
replace: '',
},
]
},
}, },
{ {
loader: 'sass-loader', loader: 'sass-loader',
} options: {
sourceMap: true,
outputStyle: 'compressed',
},
},
] ]
} },
{
test: /\.s?css$/,
exclude: /patternfly-4-cockpit.scss/,
use: [
extract.loader,
{
loader: 'css-loader',
options: {
sourceMap: true,
url: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
outputStyle: 'compressed',
},
},
]
},
] ]
}, },
plugins: plugins plugins: plugins