Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for scoped versioning #877

Merged
merged 28 commits into from Jan 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
43566da
Add utilities to scope core Fabric styles to the current major version
Jahnp Oct 5, 2016
fbabf38
Add template for Fabric.Scoped.scss, which will consume package.json …
Jahnp Dec 2, 2016
0bb585e
Add temp folder to config and update .gitignore to exclude it
Jahnp Dec 2, 2016
052562d
Add scoped pre-build task as dependency of Fabric-buildStyles. Remove…
Jahnp Dec 2, 2016
511e31b
Scope specific Fabric Core imports
Jahnp Dec 2, 2016
898b1d7
Add scoping documentation page
Jahnp Dec 2, 2016
650459e
Remove static scoped styles
Jahnp Dec 2, 2016
b0d33aa
Scope icon font definitions and CDN references to point to versioned …
Jahnp Dec 2, 2016
66a44ed
Include patch version in scope class, so full scope class would be of…
Jahnp Dec 2, 2016
d227daf
Add fonts to scoped output
Jahnp Dec 2, 2016
127fce3
Merge branch 'master' of https://github.com/OfficeDev/office-ui-fabri…
Jahnp Dec 2, 2016
d0fa7d3
Add ghdocs documentation for scoping
Jahnp Dec 2, 2016
770bc52
- Merge master and cleanup conflicts.
Jahnp Dec 17, 2016
fd1061c
Split out typography classes and Segoe @font-face rules into _Typogra…
Jahnp Dec 17, 2016
b4ae9cc
Remove unnecessary comments
Jahnp Dec 17, 2016
4d34b4f
Rewrite scoping example documentation
Jahnp Dec 17, 2016
ba136da
Remove unnecessary ScopingPage styles
Jahnp Dec 17, 2016
51f8223
Remove scoping sample, since this has been documented elsewhere
Jahnp Dec 17, 2016
8b96464
Update scoping sample & documentation to reflect the currrent version…
Jahnp Dec 17, 2016
9483e8e
Move Segoe @font-face definitions into _Font.Definitions and move the…
Jahnp Dec 17, 2016
250ae72
Change _IconFont.scss to _Icon.Definitions.scss to match other @font-…
Jahnp Dec 17, 2016
9816592
Add _Icon.Definitions.scss
Jahnp Dec 17, 2016
2e186b1
Prefix global scoping vars with 'ms-'. Separate scoping suffix as a s…
Jahnp Dec 20, 2016
4494dcb
Version-scope @keyframes definitions and uses
Jahnp Dec 20, 2016
e554ea0
Merge branch 'master' into jahnp/scoped-versioning
Jahnp Jan 3, 2017
b401d7a
Inline version number instead of file based
micahgodbolt Jan 4, 2017
3fc8061
removed old task and templates. changed variable format and upated co…
micahgodbolt Jan 4, 2017
fc043ac
Merge pull request #890 from OfficeDev/mgodbolt/scoped-versioning
Jan 4, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -11,6 +11,7 @@ npm-debug.log
*.sublime-workspace
docs.css
dist
temp

# Docs files
docs/app
Expand Down
43 changes: 43 additions & 0 deletions ghdocs/SCOPING.md
@@ -0,0 +1,43 @@
# Version scoping
"Version-scoping" is a variation of Fabric Core which provides a wrapped or "scoped" version of every Fabric class under a modifier of the `.ms-Fabric` base class, which is tied to the current version. If the version is `5.1.0`, this "scope class" would take the form `.ms-Fabric--v5-1-0`.

## Why is this useful?
Version scoping is targeted at the scenario where multiple versions of Fabric Core may live on a single web page, whose differences between major versions could potentially introduce regressions or conflicts.

A practical example of this is the SharePoint Web Parts used for publishing articles. Web Parts are effectively miniature applications, each of which can depend on their own version of Fabric. To ensure that they can continue to exist on the same publishing page without:
1. Risking regressions from other web parts that might be using an older version of Fabric, and
2. Forcing them to consume the latest (which would likely require work to update),

the Web Part developer can scope the Fabric styles for their entire Web Part to the particular version that was used during development.

## Usage
Usage of version scoping is straightforward. Simply append the "versioned class" to the container element you wish to scope, then use Fabric Core classes as you normally would.

Here's a minimal HTML page demonstrating this:

```html
<html>
<head>
<!-- Link to the scoped styles for the current version of Fabric Core -->
<link rel="stylesheet" href="/fabric-5.1.0.scoped.css">
</head>
<body>
<!-- Add the scoping class -->
<div class="ms-Fabric--v5-1-0">
<!--
Use Fabric as usual. These styles will be unaffected
by other versions of Fabric. They also cannot be used
outside of a scoped class.
-->
<h1 class="ms-font-su">Some scoped title <i class="ms-Icon ms-Icon--Info"></i></h1>
</div>
</body>
</html>
```

## Notes on fonts
Icon `@font-face` definitions (including the `font-family` name) and their font files are only scoped to **major versions** of Fabric. What this means is that all of the normal, additive changes to icon font files that occur within a major version's lifetime will be applied to a single font file, rather than maintaining separate font files for each minor or patch release. What this means is that there will not be `fabricmdl2icons-5.1.0.ttf`, `fabricmdl2icons-5.2.0.ttf`, etc. There will simply be `fabricmdl2icons-5.ttf`.

This is because generally icon font changes are purely additive, and rarely change significantly even between minor versions. However, the CSS classes for those icons (e.g. `ms-Icon--X`) *are* version scoped like normal classes. Also, note that the "unscoped" version of the icon font file as used today will still be available.

Finally, the standard, "unscoped" `@font-face` definitions to the Segoe UI webfonts are included in scoped Fabric unchanged. These fonts almost never change appreciably and are not considered risky to depend on between major releases.
47 changes: 41 additions & 6 deletions gulp/FabricBuild.js
Expand Up @@ -7,14 +7,25 @@ var BuildConfig = require('./modules/BuildConfig');
var ConsoleHelper = require('./modules/ConsoleHelper');
var ErrorHandling = require('./modules/ErrorHandling');
var Plugins = require('./modules/Plugins');
var pkg = require('../package.json');

var versionParts = pkg.version.split('.');

var version = {
major: versionParts[0],
minor: versionParts[1],
patch: versionParts[2]
}

var versionCommaDelim = pkg.version.split('.').join(',');

//
// Clean/Delete Tasks
// ----------------------------------------------------------------------------

// Clean out the distribution folder.
gulp.task('Fabric-nuke', function () {
return Plugins.del.sync([Config.paths.distCSS, Config.paths.distSass]);
return Plugins.del.sync([Config.paths.distCSS, Config.paths.distSass, Config.paths.temp]);
});


Expand All @@ -24,9 +35,10 @@ gulp.task('Fabric-nuke', function () {

// Copy all Sass files to distribution folder.
gulp.task('Fabric-copyAssets', function () {
var moveSass = gulp.src([Config.paths.srcSass + '/**/*'])
var moveSass = gulp.src([Config.paths.srcSass + '/**/*', !Config.paths.srcSass + '/Fabric.Scoped.scss'])
.pipe(Plugins.plumber(ErrorHandling.onErrorInPipe))
.pipe(Plugins.changed(Config.paths.distSass))
.pipe(Plugins.replace('<%= fabricVersion %>', versionCommaDelim))
.pipe(Plugins.gulpif(Config.debugMode, Plugins.debug({
title: "Moving Sass files over to Dist"
})))
Expand All @@ -38,8 +50,6 @@ gulp.task('Fabric-copyAssets', function () {
// Sass tasks
// ----------------------------------------------------------------------------

// Build Sass files for core Fabric into LTR and RTL CSS files.

gulp.task('Fabric-buildStyles', function () {
var fabric = gulp.src(BuildConfig.srcPath + '/' + 'Fabric.' + BuildConfig.fileExtension)
.pipe(Plugins.plumber(ErrorHandling.onErrorInPipe))
Expand All @@ -64,8 +74,32 @@ gulp.task('Fabric-buildStyles', function () {
}))
.pipe(Plugins.header(Banners.getBannerTemplate(), Banners.getBannerData()))
.pipe(Plugins.header(Banners.getCSSCopyRight(), Banners.getBannerData()))
.pipe(gulp.dest(Config.paths.distCSS));

var fabricScoped = gulp.src(BuildConfig.srcPath + '/' + 'Fabric.Scoped.' + BuildConfig.fileExtension)
.pipe(Plugins.gulpif(Config.debugMode, Plugins.debug({
title: "Building Core Fabric Scoped " + BuildConfig.fileExtension + " File"
})))
.pipe(Plugins.header(Banners.getBannerTemplate(), Banners.getBannerData()))
.pipe(Plugins.header(Banners.getCSSCopyRight(), Banners.getBannerData()))
.pipe(Plugins.replace('<%= fabricVersion %>', versionCommaDelim))
.pipe(BuildConfig.processorPlugin().on('error', BuildConfig.compileErrorHandler))
.pipe(Plugins.rename('fabric-' + version.major + '.' + version.minor + '.' + version.patch + '.scoped.css'))
.pipe(Plugins.autoprefixer({
browsers: ['last 2 versions', 'ie >= 9'],
cascade: false
}))
.pipe(Plugins.cssbeautify())
.pipe(Plugins.csscomb())
.pipe(gulp.dest(Config.paths.distCSS))
.pipe(Plugins.rename('fabric-' + version.major + '.' + version.minor + '.' + version.patch + '.scoped.min.css'))
.pipe(Plugins.cssMinify({
safe: true
}))
.pipe(Plugins.header(Banners.getBannerTemplate(), Banners.getBannerData()))
.pipe(Plugins.header(Banners.getCSSCopyRight(), Banners.getBannerData()))
.pipe(gulp.dest(Config.paths.distCSS));

// Build full and minified Fabric RTL CSS.
var fabricRtl = gulp.src(BuildConfig.srcPath + '/' + 'Fabric.Rtl.' + BuildConfig.fileExtension)
.pipe(Plugins.plumber(ErrorHandling.onErrorInPipe))
Expand All @@ -92,8 +126,9 @@ gulp.task('Fabric-buildStyles', function () {
.pipe(Plugins.header(Banners.getBannerTemplate(), Banners.getBannerData()))
.pipe(Plugins.header(Banners.getCSSCopyRight(), Banners.getBannerData()))
.pipe(gulp.dest(Config.paths.distCSS));

// Merge all current streams into one.
return Plugins.mergeStream(fabric, fabricRtl);
return Plugins.mergeStream(fabric, fabricScoped, fabricRtl);
});

//
Expand Down
1 change: 1 addition & 0 deletions gulp/modules/Config.js
Expand Up @@ -17,6 +17,7 @@ var Config = function() {
src: 'src',
componentsPath : 'src/components',
srcLibPath: 'lib',
temp: 'temp'
};

this.paths.distComponents = this.paths.dist + '/components';
Expand Down
1 change: 1 addition & 0 deletions gulp/modules/Plugins.js
Expand Up @@ -35,6 +35,7 @@ var Plugins = function() {
this.path = require('path');
this.pkg = require('../../package.json');
this.fs = require('fs');
this.replace = require('gulp-replace');
};

module.exports = new Plugins();
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -35,6 +35,7 @@
"gulp-nuget-pack": "0.0.6",
"gulp-plumber": "^1.0.1",
"gulp-rename": "^1.2.2",
"gulp-replace": "^0.5.4",
"gulp-sass": "^3.0.0",
"gulp-size": "^1.0.0",
"gulp-template": "^3.0.0",
Expand All @@ -50,6 +51,5 @@
"typescript": "^2.0.3",
"walk-sync": "^0.3.0"
},
"dependencies": {
}
"dependencies": {}
}
36 changes: 36 additions & 0 deletions src/documentation/pages/Scoping/index.html
@@ -0,0 +1,36 @@
@@include('../../templates/modules/components/DocumentationPageHeader.html')
<style>
.ms-Fabric--v5-1-0 .ms-fontColor-themePrimary {
color: #ff0000;
}
</style>

<div class="docs-Styles-section" id="scoping">
<h2>Version Scoping Sample</h2>
<p>For scenarios where multiple major versions may live in the same DOM, Fabric provides a "scoped" version of all Core styles that will only apply those styles when used under a versioned wrapper class.</p>

<p>
To use scoped Fabric styles, simply add the versioned wrapper class to the parent DOM element you wish to scope, then use Fabric as usual.
</p>

<p>For example, take this following title, which uses unscoped Fabric:</p>

<pre><code>
&lt;div class="ms-font-xxl ms-fontColor-themePrimary">This title uses ms-fontColor-themePrimary from unscoped Fabric.&lt;/div&gt;
</code></pre>

<div class="ms-font-xxl ms-fontColor-themePrimary">This title uses ms-fontColor-themePrimary from unscoped Fabric.</div>

<p>To scope this title to v5.1.0, add an extra wrapper <code>div</code> around it and add both the <code>ms-Fabric</code> wrapper class and the scoping class for the current version of Fabric. Note that to illustrate this behavior for this demonstration, <code>.ms-fontColor-themePrimary</code> has been overridden with a different color when used under the <code>ms-Fabric--v5-1-0</code> version-scoping class.</p>

<pre><code>
&lt;div class="ms-Fabric ms-Fabric--v5-1-0">
&lt;div class="ms-font-xxl ms-fontColor-themePrimary">This title uses ms-fontColor-themePrimary from Fabric 5.1.0.&lt;/div&gt;
&lt;/div&gt;
</code></pre>

<div class="ms-Fabric ms-Fabric--v5-1-0">
<div class="ms-font-xxl ms-fontColor-themePrimary">This title uses ms-fontColor-themePrimary from Fabric 5.1.0.</div>
</div>
</div>
@@include('../../templates/modules/components/DocumentationPageFooter.html')
Expand Up @@ -18,5 +18,8 @@
<div class="LeftNav-item">
<a class="Localization LeftNav-link ms-border-color-themePrimary ms-font-l ms-font-color-neutralSecondary" href="/Localization">Localization</a>
</div>
<div class="LeftNav-item">
<a class="Scoping LeftNav-link ms-border-color-themePrimary ms-font-l ms-font-color-neutralSecondary" href="/Scoping">Scoping</a>
</div>
</div>
</div>
33 changes: 33 additions & 0 deletions src/sass/Fabric.Scoped.scss
@@ -0,0 +1,33 @@
// Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.

//
// Office UI Fabric
// Core styles scoped to the current major version of Fabric

// Variable is set during gulp task as comma seperated list. i.e. 5,1,0
$ms-fabric-version: <%= fabricVersion %>;

@import './References';
@import './mixins/ScopedStyles.Mixins';

// Sets a global flag to enable scoped styles within certain files
$do-scope-styles: true;

// Scope all core styles under a helper class for the current major version.
// This produces styles of the form .ms-Fabric-{version #} .ms-font-m.

@include scope-fabric {
@import './Animation';
@import './BrandIcon';
@import './Color';
@import './Font';
@import './Grid';
@import './Icon';
@import './Responsive';
@import './Utility';
@import './Wrapper';
}

// @font-face definitions do not need to be scoped
@import './Font.Definitions';
@import './Icon.Definitions';
2 changes: 2 additions & 0 deletions src/sass/Fabric.scss
Expand Up @@ -12,8 +12,10 @@
@import './Animation';
@import './BrandIcon';
@import './Color';
@import './Font.Definitions';
@import './Font';
@import './Grid';
@import './Icon.Definitions';
@import './Icon';
@import './Responsive';
@import './Utility';
Expand Down
119 changes: 119 additions & 0 deletions src/sass/_Font.Definitions.scss
@@ -0,0 +1,119 @@
// Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.

//
// Office UI Fabric
// --------------------------------------------------
// @font-face rules for Segoe UI

// Additional @font-face rules for the Leelawadee font.
@font-face {
font-family: 'Leelawadee UI';
src: local('Leelawadee UI Bold'),
url('#{$ms-font-directory}/leelawadeeui-thai/leelawadeeui-bold.woff2') format('woff2'),
url('#{$ms-font-directory}/leelawadeeui-thai/leelawadeeui-bold.woff') format('woff'),
url('#{$ms-font-directory}/leelawadeeui-thai/leelawadeeui-bold.ttf') format('truetype');
font-weight: 600;
font-style: normal;
}

@font-face {
font-family: 'Leelawadee UI';
src: local('Leelawadee UI Regular'),
url('#{$ms-font-directory}/leelawadeeui-thai/leelawadeeui-regular.woff2') format('woff2'),
url('#{$ms-font-directory}/leelawadeeui-thai/leelawadeeui-regular.woff') format('woff'),
url('#{$ms-font-directory}/leelawadeeui-thai/leelawadeeui-regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
}

@font-face {
font-family: 'Leelawadee UI';
src: local('Leelawadee UI Semilight'),
url('#{$ms-font-directory}/leelawadeeui-thai/leelawadeeui-semilight.woff2') format('woff2'),
url('#{$ms-font-directory}/leelawadeeui-thai/leelawadeeui-semilight.woff') format('woff'),
url('#{$ms-font-directory}/leelawadeeui-thai/leelawadeeui-semilight.ttf') format('truetype');
font-weight: 300;
font-style: normal;
}

// Output the standard fonts
@include SegoeUIWestEuropeanLight;
@include SegoeUIWestEuropeanRegular;
@include SegoeUIWestEuropeanSemibold;
@include SegoeUIWestEuropeanSemilight;

// Mixins to generate language-specific font faces.
@include SegoeUIArabicLight;
@include SegoeUIArabicRegular;
@include SegoeUIArabicSemibold;
@include SegoeUIArabicSemilight;

@include SegoeUICyrillicLight;
@include SegoeUICyrillicRegular;
@include SegoeUICyrillicSemibold;
@include SegoeUICyrillicSemilight;

@include SegoeUIEastEuropeanLight;
@include SegoeUIEastEuropeanRegular;
@include SegoeUIEastEuropeanSemibold;
@include SegoeUIEastEuropeanSemilight;

@include SegoeUIGreekLight;
@include SegoeUIGreekRegular;
@include SegoeUIGreekSemibold;
@include SegoeUIGreekSemilight;

@include SegoeUIHebrewLight;
@include SegoeUIHebrewRegular;
@include SegoeUIHebrewSemibold;
@include SegoeUIHebrewSemilight;

@include SegoeUIVietnameseLight;
@include SegoeUIVietnameseRegular;
@include SegoeUIVietnameseSemibold;
@include SegoeUIVietnameseSemilight;

// Generate the override classes for non-distributed fonts.
@include language-override-system-fonts(jpn, $ms-font-stack-japanese);
@include language-override-system-fonts(kor, $ms-font-stack-korean);
@include language-override-system-fonts(cmn, $ms-font-stack-chinese-simplified);
@include language-override-system-fonts(yue, $ms-font-stack-chinese-traditional);
@include language-override-system-fonts(hin, $ms-font-stack-hindi);

// Generate the override classes for web fonts.
// Thai (Leelawadee)
// tha
@include language-override-system-fonts(tha, $ms-font-stack-leelawadee);

// Arabic
// ara
@include language-override-system-fonts(ara, $ms-font-stack-arabic);

// East European
// ces, et, hrv, hun, lit, pl, lat, tur, slk, kaz
@include language-override-system-fonts(ces, $ms-font-stack-eastEuropean);
@include language-override-system-fonts(est, $ms-font-stack-eastEuropean);
@include language-override-system-fonts(hrv, $ms-font-stack-eastEuropean);
@include language-override-system-fonts(hun, $ms-font-stack-eastEuropean);
@include language-override-system-fonts(kaz, $ms-font-stack-eastEuropean);
@include language-override-system-fonts(lav, $ms-font-stack-eastEuropean);
@include language-override-system-fonts(lit, $ms-font-stack-eastEuropean);
@include language-override-system-fonts(pol, $ms-font-stack-eastEuropean);
@include language-override-system-fonts(slk, $ms-font-stack-eastEuropean);
@include language-override-system-fonts(tur, $ms-font-stack-eastEuropean);

// Cyrillic
// rus
@include language-override-system-fonts(rus, $ms-font-stack-cyrillic);

// Greek
// ell
@include language-override-system-fonts(ell, $ms-font-stack-greek);

// Hebrew
// heb
@include language-override-system-fonts(heb, $ms-font-stack-hebrew);

// Vietnamese
// vie
@include language-override-system-fonts(vie, $ms-font-stack-vietnamese);