postcss-less2scss:将 Less 转换成 Scss 的 PostCSS 插件

发布一个 PostCSS 插件:postcss-less2scss,可以将 Less 文件转换为 Scss。
* GitHub:https://www.npmjs.com/package/postcss-less2scss
* NPM:https://www.npmjs.com/package/postcss-less2scss

转换变量

转换变量的定义和使用

  • 不属于任何一个 Rule 的变量

Less:

@link-color: #428bca;

Scss:

$link-color: #428bca;
  • 在某个 Rule 中定义的变量

Less:

#main {
  @width: 5em;
  width: @width;
}

Scss:

#main {
  $width: 5em;
  width: $width;
}
  • 在 Declaration 的 value 中使用的变量

Less:

@text-color: @gray-dark;
@link-color-hover:  darken(@link-color, 10%);

Scss:

$text-color: $gray-dark;
$link-color-hover:  darken($link-color, 10%);
  • 在某个 Rule 中的一个 Declaration 的 value 中使用的变量

Less:

a:hover {
  color: @link-color-hover;
}

Scss:

a:hover {
  color: $link-color-hover;
}
  • 转换 At-Rules 中的变量

Less:

@screen-sm:                  768px;
@screen-sm-min:              @screen-sm;

.form-inline {

  // Kick in the inline
  @media (min-width: @screen-sm-min) {
    // Inline-block all the things for "inline"
    .form-group {
      display: inline-block;
      margin-bottom: 0;
      vertical-align: middle;
    }
  }
}

Scss:

$screen-sm:                  768px;
$screen-sm-min:              $screen-sm;

.form-inline {

  // Kick in the inline
  @media (min-width: $screen-sm-min) {
    // Inline-block all the things for "inline"
    .form-group {
      display: inline-block;
      margin-bottom: 0;
      vertical-align: middle;
    }
  }
}

Variable Interpolation

  • 转换选择器中的 variable interpolation

Less:

// Variables
@my-selector: banner;

// Usage
.@{my-selector} {
  font-weight: bold;
  line-height: 40px;
  margin: 0 auto;
}

Scss:

// Variables
$my-selector: banner;

// Usage
.#{$my-selector} {
  font-weight: bold;
  line-height: 40px;
  margin: 0 auto;
}

转换 Mixins

  • 转换 Mixins 的定义(可以支持默认参数)

Less:

.alert-variant(@background; @border; @text-color) {
  background-color: @background;
  border-color: @border;
  color: @text-color;

  hr {
    border-top-color: darken(@border, 5%);
  }
  .alert-link {
    color: darken(@text-color, 10%);
  }
}

Scss:

@mixin alert-variant($background, $border, $text-color) {
  background-color: $background;
  border-color: $border;
  color: $text-color;

  hr {
    border-top-color: darken($border, 5%);
  }
  .alert-link {
    color: darken($text-color, 10%);
  }
}
  • 转换 Mixins 的使用

Less:

.a {
    .center-block;
}

Scss:

.a {
    @include center-block;
}
  • 支持 Mixins 的具有默认值的参数

Less:

@state-success-text:             #3c763d;
@state-success-bg:               #dff0d8;
@state-success-border:           darken(spin(@state-success-bg, -10), 5%);

@state-info-text:                #31708f;
@state-info-bg:                  #d9edf7;
@state-info-border:              darken(spin(@state-info-bg, -10), 7%);

@state-warning-text:             #8a6d3b;
@state-warning-bg:               #fcf8e3;
@state-warning-border:           darken(spin(@state-warning-bg, -10), 5%);

@state-danger-text:              #a94442;
@state-danger-bg:                #f2dede;
@state-danger-border:            darken(spin(@state-danger-bg, -10), 5%);

.box-shadow(@shadow) {
  -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1
          box-shadow: @shadow;
}

.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {
  // Color the label and help text
  .help-block,
  .control-label,
  .radio,
  .checkbox,
  .radio-inline,
  .checkbox-inline,
  &.radio label,
  &.checkbox label,
  &.radio-inline label,
  &.checkbox-inline label  {
    color: @text-color;
  }
  // Set the border and box shadow on specific inputs to match
  .form-control {
    border-color: @border-color;
    .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work
    &:focus {
      border-color: darken(@border-color, 10%);
      @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);
      .box-shadow(@shadow);
    }
  }
  // Set validation states also for addons
  .input-group-addon {
    color: @text-color;
    border-color: @border-color;
    background-color: @background-color;
  }
  // Optional feedback icon
  .form-control-feedback {
    color: @text-color;
  }
}

// Feedback states
.has-success {
  .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);
}
.has-warning {
  .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);
}
.has-error {
  .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);
}

Scss:

$state-success-text:             #3c763d;
$state-success-bg:               #dff0d8;
$state-success-border:           darken(adjust_hue($state-success-bg, -10), 5%);

$state-info-text:                #31708f;
$state-info-bg:                  #d9edf7;
$state-info-border:              darken(adjust_hue($state-info-bg, -10), 7%);

$state-warning-text:             #8a6d3b;
$state-warning-bg:               #fcf8e3;
$state-warning-border:           darken(adjust_hue($state-warning-bg, -10), 5%);

$state-danger-text:              #a94442;
$state-danger-bg:                #f2dede;
$state-danger-border:            darken(adjust_hue($state-danger-bg, -10), 5%);

@mixin box-shadow($shadow) {
  -webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1
          box-shadow: $shadow;
}

@mixin form-control-validation($text-color: #555, $border-color: #ccc, $background-color: #f5f5f5) {
  // Color the label and help text
  .help-block,
  .control-label,
  .radio,
  .checkbox,
  .radio-inline,
  .checkbox-inline,
  &.radio label,
  &.checkbox label,
  &.radio-inline label,
  &.checkbox-inline label  {
    color: $text-color;
  }
  // Set the border and box shadow on specific inputs to match
  .form-control {
    border-color: $border-color;
    @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work
    &:focus {
      border-color: darken($border-color, 10%);
      $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($border-color, 20%);
      @include box-shadow($shadow);
    }
  }
  // Set validation states also for addons
  .input-group-addon {
    color: $text-color;
    border-color: $border-color;
    background-color: $background-color;
  }
  // Optional feedback icon
  .form-control-feedback {
    color: $text-color;
  }
}

// Feedback states
.has-success {
  @include form-control-validation($state-success-text, $state-success-text, $state-success-bg);
}
.has-warning {
  @include form-control-validation($state-warning-text, $state-warning-text, $state-warning-bg);
}
.has-error {
  @include form-control-validation($state-danger-text, $state-danger-text, $state-danger-bg);
}

转换函数

字符串函数

  • 转换 CSS 转义函数,也就是:~”xxx”

Less:

@input-border-focus:             #66afe9;

.box-shadow(@shadow) {
  -webkit-box-shadow: @shadow; // iOS &lt;4.3 & Android &lt;4.1
  box-shadow: @shadow;
}

.form-control-focus(@color: @input-border-focus) {
  @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);
  &:focus {
    border-color: @color;
    outline: 0;
    .box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}");
  }
}

.form-control {
  .form-control-focus();
}

Scss:

$input-border-focus:             #66afe9;

@mixin box-shadow($shadow) {
  -webkit-box-shadow: $shadow; // iOS &lt;4.3 & Android &lt;4.1
  box-shadow: $shadow;
}

@mixin form-control-focus($color: $input-border-focus) {
  $color-rgba: rgba(red($color), green($color), blue($color), .6);
  &:focus {
    border-color: $color;
    outline: 0;
    @include box-shadow(#{inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba});
  }
}

.form-control {
  @include form-control-focus();
}

颜色函数

  • 将 Less 的 spin() 函数转换为 Scss 的 adjust_hue() 函数

Less:

@state-success-border:           darken(spin(@state-success-bg, -10), 5%);

Scss:

$state-success-border:           darken(adjust_hue($state-success-bg, -10), 5%);

转换 @import At-Rules

Less:

@import "foo";
@import "foo.less";
@import "foo.php";
@import "foo.css";

Scss:

@import "foo";
@import "foo";
@import "foo";
@import "foo.css";

如果使用 postcss-less2scss 插件

const postcss = require('postcss')
const syntax = require('postcss-less')
const converter = require('postcss-less2scss')

const lessText = `
// Variables
@link-color:        #428bca; // sea blue
@link-color-hover:  darken(@link-color, 10%);

// Usage
a,
.link {
  color: @link-color;
}
a:hover {
  color: @link-color-hover;
}
.widget {
  color: #fff;
  background: @link-color;
}
`
const scssText = postcss([converter])
  .process(lessText, { syntax })
  .css
console.log('lessText = ', lessText, ', \nscssText = ', scssText)

和 gulp 集成

/**
 * Use postcss-less2scss to convert bootstrap v3.3.7 styles from less to scss
 */
gulp.task('less2scss', () => {
  return gulp.src('assets/less/bootstrap3/**/*.less')
    .pipe(postcss([less2scss], {
      syntax: less
    }))
    .pipe(rename(path => {
      if (path.basename !== 'bootstrap') {
        path.basename = '_' + path.basename
      }
      path.extname = '.scss'
    }))
    .pipe(gulp.dest('build/scss/bootstrap3/'))
})

Web Storage

HTML5 的 Web Storage 可以让 Web 页面在客户端浏览器中以键值对的形式在本地存储数据。
这些数据可以是临时的(浏览器一关就自动删除),或者是长期存在的(无论多少天之后打开网站,仍然可以访问这些数据)。
Web Storage 的意思是供 Web 使用的 Storage,不是存储在 Web 上的,都是存储在本地的。所以某些浏览器厂商又把它叫做“本地存储”或者“DOM存储”。
Web Storage 和很多其他的规范一样,原先是 HTML5 规范的一部分,后来被 W3C 归类划分给抽离出来形成了单独的一份标准。

讲义大纲

  • 什么是 Web Storage ?
  • 浏览器支持情况
  • 特性检测
  • Web Storage 快速示例
  • 使用 Web Storage
    • 删除数据项
    • 查找所有数据项
    • 保存数值
    • 保存对象
    • 响应存储变化

HTML5 离线功能详解 – 构建 Offline Web Application

HTML5 提供的一种应用缓存机制可以让基于 Web 的应用离线运行。开发者可以指定让浏览器缓存哪些资源以便在离线状态下可用。这样即使在离线状态下,用户打开(或刷新)应用页面时,已经缓存过的应用程序还可以继续加载和运行。

使用应用程序缓存的三个好处:

  • 离线浏览:用户即使在离线状态下也可以访问网站
  • 速度:缓存的资源是保存在本地的,因此加载起来更快速
  • 降低服务器负载:浏览器只从服务器下载变更了的内容

讲义大纲

  • Quick Start: What & How?
    • 什么是 Offline Web applications?
    • 快速 Demo: 把网页转成离线应用的三个步骤
    • 浏览器支持情况和调试,及缓存空间大小限制
  • manifest 语法,编写和更新
  • 实用缓存技术
    • 访问未缓存内容
    • 添加后备内容
    • 网络连接检测的几种方法
    • 缓存过程的事件流
    • 使用 JavaScript API: applicationCache
    • 特性检测
  • 相关资源

在线阅读
PPT 下载

Pointer Lock API

指针锁定(以前叫做 鼠标锁定) 提供了一种输入方法,这种方法是基于鼠标随着时间推移的运动的(也就是说,deltas),而不仅是鼠标光标的绝对位置。通过它可以访问原始的鼠标运动,把鼠标事件的目标锁定到一个单独的元素,这就消除了鼠标在一个单独的方向上到底可以移动多远这方面的限制,并从视图中删去光标。

这个 API 对于需要大量的鼠标输入来控制运动,旋转物体,以及更改项目的应用程序来说非常有用。对高度视觉化的应用程序尤其重要,例如那些使用第一人称视角的应用程序,以及 3D 视图和建模。 (更多…)

使用 IndexedDB

IndexedDB 是一种可以让你在用户的浏览器内持久化存储数据的方法。IndexedDB 为生成 Web Application 提供了丰富的查询能力,使我们的应用在在线和离线时都可以正常工作。

关于本文档

本篇教程将教会你如何使用 IndexedDB 的异步 API。如果你对 IndexedDB 还不熟悉,你应该首先阅读有关 IndexedDB 的基本概念

有关 IndexedDB API 的参考手册,请参见 IndexedDB 这篇文章及其子页面,包括 IndexedDB 使用的对象类型,以及同步和异步 API 的方法。

基本模式

IndexedDB 鼓励使用的基本模式如下所示:

  1. 打开数据库并且开始一个事务。
  2. 创建一个 object store。
  3. 构建一个请求来执行一些数据库操作,像增加或提取数据等。
  4. 通过监听正确类型的 DOM 事件以等待操作完成。
  5. 在操作结果上进行一些操作(可以在 request 对象中找到) (更多…)

没有 setVersion 了,现在是 onupgradeneeded !

默认情况下,IndexedDB 数据库是没有版本号的。新版本的 IndexedDB 规范不支持调用setVersion()方法为数据库指定一个版本号(传入一个表示版本号的字符串);代替的方法是在 open() 的时侯传入表示版本号的字符串,同时使用 onupgradeneeded 事件代替了 setVersion() 方法。onupgradeneeded 事件会在 onsuccess 之前被调用。[sourcecode lang=”javascript”]
tfan.indexedDB.open = function() {
var request = indexedDB.open(‘parser17103’, 1);

request.onupgradeneeded = function(event) {
console.log("onupgradeneeded", event.currentTarget.result);
var store = event.currentTarget.result.createObjectStore(‘question’, {keyPath: "question_id"});
tfan.indexedDB.getAllQuestionItems();
};

request.onsuccess = function(event) {
console.log("open success");
tfan.indexedDB.db = event.target.result;
};

request.onerror = tfan.indexedDB.onerror;
};</pre>
</article>
[/sourcecode]

更多请参考:

HTML5 Web 开发培训讲义

为 HTML5 培训准备的部分讲义,希望对大家能有所帮助。
(Note: 观看 slides 的时候,键盘上下左右键可以控制翻页,还可以使用 Ctrl + (+ 或 -) 控制显示大小)

HTML5 技术体系简介

HTML5 新元素

Web Storage

Web Workers – JavaScript 并发

HTML5 文件访问

JavaScript 最佳实践

CSS3 新特性

HTML5 Canvas, Audio & Video

HTML5 Geolocation – 地理位置信息

构建离线 Web 应用

设备方向和多点触控

HTML5 Web Socket – 持久连接和双向通信