Gerald 9 роки тому
батько
коміт
701fc450fd

+ 0 - 2
.gitignore

@@ -1,3 +1 @@
-examples/test.html
-examples/ua-parser.min.js
 node_modules/

+ 0 - 3
.travis.yml

@@ -1,3 +0,0 @@
-language: node_js
-node_js:
-  - "0.12"

+ 11 - 12
README.md

@@ -2,6 +2,7 @@
 ===
 
 ![Bower](https://img.shields.io/bower/v/duoshuo-ua.svg)
+![npm](https://img.shields.io/npm/v/duoshuo-ua.svg)
 
 多说作为一个第三方评论功能感觉很不错的样子,而且可定制性很强。
 
@@ -9,20 +10,17 @@
 
 安装
 ---
-可以通过bower安装:
+* Bower
 
-``` sh
-$ bower install duoshuo-ua
-```
-
-dist中各文件的说明:
+  ``` sh
+  $ bower install duoshuo-ua
+  ```
 
-1. **duoshuo-ua-core.min.js**是不集成ua-parser和CSS精简版,便于自行扩展。
-1. **duoshuo-ua-parser.min.js**集成轻量级的ua-parser,但是不集成CSS。
-1. **duoshuo-ua-parser-css.min.js**集成轻量级的ua-parser和CSS,提供默认的显示方案。
-1. **duoshuo-ua.min.css**为默认的样式文件。
+* NPM
 
-默认将使用**duoshuo-ua-parser.min.js**和**duoshuo-ua.min.css**。
+  ``` sh
+  $ npm install duoshuo-ua
+  ```
 
 文档
 ---
@@ -42,10 +40,11 @@ duoshuoQuery中可以定义`myIds`和`getUAString`函数:
 ``` HTML
 <html>
 <head>
+<link rel="stylesheet" href="dist/duoshuo-ua.css">
 
 <!-- 第1部分:在embed.js之前定义duoshuoQuery和加载duoshuo-ua
 两者顺序可以交换-->
-<script src="dist/duoshuo-ua-parser-css.min.js"></script>
+<script src="dist/duoshuo-ua.js"></script>
 <script>var duoshuoQuery={short_name:'test',myIds:[1234567]};</script>
 
 <!-- 第2部分:可写成异步加载,必须写在第1部分后面 -->

+ 2 - 2
bower.json

@@ -6,8 +6,8 @@
   ],
   "description": "Plugin of duoshuo to show operating systems and browsers for duoshuo comments.",
   "main": [
-	  "dist/duoshuo-ua-parser.min.js",
-	  "dist/duoshuo-ua.min.css"
+	  "dist/duoshuo-ua.js",
+	  "dist/duoshuo-ua.css"
   ],
   "keywords": [
     "duoshuo",

Різницю між файлами не показано, бо вона завелика
+ 0 - 8
dist/duoshuo-ua-core.min.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 8
dist/duoshuo-ua-parser-css.min.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 8
dist/duoshuo-ua-parser.min.js


+ 20 - 0
dist/duoshuo-ua.css

@@ -0,0 +1,20 @@
+#ds-reset .ds-os,
+#ds-reset .ds-br,
+#ds-reset .ds-webmaster {
+	display: inline-block;
+	border-radius: .3em;
+	margin-left: .5em;
+	padding: .3em;
+}
+#ds-reset .ds-os {
+	color: white;
+	background: dodgerblue;
+}
+#ds-reset .ds-br {
+	color: yellow;
+	background: green;
+}
+#ds-reset .ds-webmaster {
+	border: 1px solid red;
+	color: red;
+}

+ 242 - 0
dist/duoshuo-ua.js

@@ -0,0 +1,242 @@
+/**
+ * Duoshuo UA Plugin
+ * @version v1.0.6
+ * @license MIT
+ * @author Gerald <gera2ld@163.com>
+ */
+!function(){
+/**
+ * 多说User-Agent插件核心脚本
+ * 用于监听DUOSHUO及评论加载过程并执行注入
+ *
+ * @author Gerald <gera2ld@163.com>
+ *
+ * Optional requirements:
+ *   ./default.js
+ */
+
+var _this = this;
+
+function emptyString(local) {
+	return '';
+}
+
+var myIds;
+function callBefore(local, args) {
+  if (!myIds) {
+    myIds = duoshuoQuery.myIds || [];
+    if (!myIds.slice) myIds = [myIds];
+    myIds.reverse();
+  }
+
+	var e = args[0];
+	if (args.length == 1)	// embed.unstable.js
+		e = e.post;
+
+	local.agent = e.agent;
+  local.webmaster = 0;
+	var id = e.author_id;
+  for (var i = myIds.length; i--; )
+    if (myIds[i] == id) {
+      local.webmaster = id;
+      break;
+    }
+}
+
+function callAfter(local, args) {
+	var res = local.result;
+	var i = res.indexOf('<div class="ds-comment-header">');
+	var j = res.indexOf('</div>', i);
+	var func = duoshuoQuery.getUAString || getUAString || emptyString;
+	local.result = res.slice(0, j) + func.call(_this, local) + res.slice(j);
+}
+
+function init() {
+	var post = DUOSHUO.templates.post;
+	DUOSHUO.templates.post = function () {
+		var local = {};
+		var args = arguments;
+		callBefore.call(this, local, args);
+		local.result = post.apply(this, args);
+		callAfter.call(this, local, args);
+		return local.result;
+	}
+}
+
+function observeProperty(item, key, callback) {
+	function callbackOnce() {
+		var cb = callback;
+		if (cb) {
+			callback = null;
+			cb();
+		}
+	}
+	var value;
+	if (item[key]) callbackOnce();
+	else Object.defineProperty(item, key, {
+		get: function () {return value;},
+		set: function (val) {
+			value = val;
+			callbackOnce();
+		},
+		configurable: true,
+	});
+}
+
+function observePropertyChain(item, keys, callback) {
+	function observe() {
+		observeProperty(item, key, function () {
+			item = item[key];
+			if(key = keys.shift()) observe();
+			else callback();
+		});
+	}
+	var key = keys.shift();
+	observe();
+}
+
+observePropertyChain(window, ['DUOSHUO', 'templates', 'post'], init);
+
+/**
+* User-Agent parser
+* @author Gerald <gera2ld@163.com>
+*/
+
+this.UAParser = function () {
+  var mapper = {
+    reg: function (str, maps) {
+      return str.replace(maps[0], maps[1]);
+    },
+    str: function (str, maps) {
+      return (str in maps) ? maps[str] : maps[''];
+    },
+    ieVer: function (str) {
+      return parseInt(str, 10) + 4;
+    },
+  };
+  var maps = {
+    winVer: {
+      '4.90': 'ME',
+      'NT3.51': 'NT 3.11',
+      'NT4.0': 'NT 4.0',
+      'NT 5.0': '2000',
+      'NT 5.1': 'XP',
+      'NT 5.2': 'XP',
+      'NT 6.0': 'Vista',
+      'NT 6.1': '7',
+      'NT 6.2': '8',
+      'NT 6.3': '8.1',
+      'NT 6.4': '10',
+      'NT 10.0': '10',
+      'ARM': 'RT',
+      '': '山寨版',
+    },
+  };
+  var NAME = 'name';
+  var VERSION = 'version';
+  var CLASS = 'cls';
+  var CLS_WIN = [CLASS, 'windows'];
+  var rules = {
+    os: [
+      // Windows
+      [/(Windows Phone)(?: OS)? ?([^; )]*)/i,
+        [NAME, VERSION, CLS_WIN]],
+      [/(Windows) ([^;)]*)/i,
+        [NAME, [VERSION, mapper.str, maps.winVer], CLS_WIN]],
+      [/\b(Windows)\b/i,
+        [NAME, [VERSION, '超级山寨版'], CLS_WIN]],
+      // Mac
+      [/(iPhone|iPod|iPad|Mac OS X)/i,
+        [NAME, [CLASS, 'mac']]],
+      // Android
+      [/(Android) ?([^; )]*)/i,
+        [NAME, VERSION, [CLASS, 'android']]],
+      // Linux
+      [/(Ubuntu|Linux)/i,
+        [NAME, [CLASS, 'linux']]],
+      [/()/i,
+        [[NAME, '山寨操作系统'], [CLASS, 'other']]],
+    ],
+    browser: [
+      // Opera
+      [/(Opera Mini)\/(\d+)/i,
+        [NAME, VERSION]],
+      [[/(OPR)\/(\S+)/i, /(Presto)\/.*?Version\/(\S+)/i],
+        [[NAME, 'Opera'], VERSION]],
+      // Chromium based browsers
+      [/(Maxthon|Vivaldi)\/(\S+)/i,
+        [NAME, VERSION]],
+      // Chrome
+      // Chrome must be checked after other Chromium base browsers are checked
+      [/(Chrome)\/(\S+)/i,
+        [NAME, VERSION]],
+      // UC/QQ
+      [/(UC|QQ)Browser\/(\S+)/i,
+        [[NAME, mapper.reg, [/$/, '浏览器']], VERSION]],
+      // Safari
+      [/Version\/(\S+) .*?(Safari)\//i,
+        [VERSION, NAME]],
+      // Firefox
+      [/(Firefox)\/(\S+)/i,
+        [NAME, VERSION]],
+      // IE
+      [/MS(IE) (\d+)\.0/i,
+        [[NAME, 'Internet Explorer'], VERSION]],
+      [/(Trident)\/(\d+)\.0/i,
+        [[NAME, 'Internet Explorer'], [VERSION, mapper.ieVer]]],
+      [/()/i,
+        [[NAME, '山寨浏览器']]],
+    ],
+  };
+  function getResult(matches, keys) {
+    var res = {};
+    keys.forEach(function(key, i) {
+      var match = matches[i + 1];
+      if (Array.isArray(key)) {
+        if (typeof key[1] == 'function')
+          res[key[0]] = key[1](match, key[2]);
+        else res[key[0]] = key[1];
+      } else res[key] = match;
+    });
+    return res;
+  }
+  function getString(obj) {
+    var str = obj.name;
+    if (obj.version)
+      str += ' ' + obj.version;
+    return str;
+  }
+  function parse(agent) {
+    var result = {};
+    for (var key in rules)
+      rules[key].some(function (rule) {
+        var regex = rule[0];
+        var attrs = rule[1];
+        if (!Array.isArray(regex))
+          regex = [regex];
+        return regex.some(function(re) {
+          var matches = agent.match(re);
+          if (matches) {
+            result[key] = getResult(matches, attrs);
+            return true;
+          }
+        });
+      });
+    return result;
+  }
+
+  return {
+    parse: parse,
+    getString: getString,
+  };
+}();
+
+var getUAString = function (local) {
+  var UAParser = this.UAParser;
+  var agent = UAParser.parse(local.agent);
+  return '<div class="ds-os">' + UAParser.getString(agent.os) + '</div>' +
+    '<div class="ds-br">' + UAParser.getString(agent.browser) + '</div>' +
+    (local.webmaster ? '<div class=ds-webmaster>站长</div>' : '');
+};
+
+}.call({});

+ 0 - 1
dist/duoshuo-ua.min.css

@@ -1 +0,0 @@
-#ds-reset .ds-br,#ds-reset .ds-os,#ds-reset .ds-webmaster{display:inline-block;border-radius:.3em;margin-left:.5em;padding:.3em}#ds-reset .ds-os{color:#fff;background:#1e90ff}#ds-reset .ds-br{color:#ff0;background:green}#ds-reset .ds-webmaster{border:1px solid red;color:red}

+ 2 - 2
examples/example.html

@@ -3,14 +3,14 @@
 	<head>
 		<meta charset=utf-8 />
 		<title>Test DUOSHUO</title>
+    <link rel="stylesheet" href="../dist/duoshuo-ua.css">
 		<script>
 			var duoshuoQuery={
 				short_name:'official',
 				myIds:[1234567],
 			};
 		</script>
-		<!-- 使用集成ua-parser和默认CSS的版本 -->
-		<script src="../dist/duoshuo-ua-parser-css.min.js"></script>
+		<script src="../dist/duoshuo-ua.js"></script>
 		<script src="http://static.duoshuo.com/embed.js"></script>
 	</head>
 	<body>

+ 20 - 71
gulpfile.js

@@ -1,20 +1,11 @@
-var gulp = require('gulp');
-var wrap = require('gulp-wrap');
-var rename = require('gulp-rename');
-var concat = require('gulp-concat');
-var merge2 = require('merge2');
-var uglify = require('gulp-uglify');
-var minifycss = require('gulp-minify-css');
-var css2js = require('gulp-css2js');
-var header = require('gulp-header');
-var clone = require('gulp-clone');
-var order = require('gulp-order');
-var pkg = require('./package.json');
-var func_wrap = '!function () {\n<%=contents%>\n}.call({});';
-var banner = [
+const gulp = require('gulp');
+const wrap = require('gulp-wrap');
+const concat = require('gulp-concat');
+const header = require('gulp-header');
+const pkg = require('./package.json');
+const banner = [
 	'/**',
-	' * <%= pkg.title %> - <%= subtitle %>',
-	' * <%= description %>',
+	' * <%= pkg.title %>',
 	' * @version v<%= pkg.version %>',
 	' * @license <%= pkg.license %>',
 	' * @author <%= pkg.author %>',
@@ -22,62 +13,20 @@ var banner = [
 	'',
 ].join('\n');
 
-gulp.task('build-core', function () {
-	return gulp.src(['./src/core.js'])
-		.pipe(wrap(func_wrap))
-		.pipe(uglify())
-		.pipe(header(banner, {
-			pkg: pkg,
-			subtitle: '精简版',
-			description: '此版本不集成ua-parser,需要自行设置getUAString',
-		}))
-		.pipe(rename('duoshuo-ua-core.min.js'))
-		.pipe(gulp.dest('./dist'));
-});
+gulp.task('build-js', () => (
+  gulp.src('src/*.js')
+  .pipe(concat('duoshuo-ua.js'))
+  .pipe(wrap('!function(){\n<%=contents%>\n}.call({});'))
+  .pipe(header(banner, {pkg: pkg}))
+  .pipe(gulp.dest('./dist'))
+));
 
-var embed_js, embed_css;
+gulp.task('build-css', () => (
+  gulp.src('src/*.css')
+  .pipe(concat('duoshuo-ua.css'))
+  .pipe(gulp.dest('./dist'))
+));
 
-gulp.task('build-with-ua-parser', function () {
-	var stream = gulp.src('./src/*.js')
-		.pipe(order([
-			'!**/default.js',
-		]))
-		.pipe(concat('duoshuo-ua-parser.js'))
-		.pipe(wrap(func_wrap))
-		.pipe(uglify())
-		.pipe(header(banner, {
-			pkg: pkg,
-			subtitle: '集成版',
-			description: '此版本集成轻量级的ua-parser但不集成CSS,提供默认的UA显示方案',
-		}));
-	embed_js = stream.pipe(clone());
-	return stream
-		.pipe(rename({suffix: '.min'}))
-		.pipe(gulp.dest('./dist'));
-});
-
-gulp.task('build-css', function () {
-	var stream = gulp.src('./src/*.css')
-		.pipe(concat('duoshuo-ua.min.css'))
-		.pipe(minifycss());
-	embed_css = stream.pipe(clone());
-	return stream
-		.pipe(gulp.dest('./dist'));
-});
-
-gulp.task('build-with-ua-parser-css', ['build-with-ua-parser', 'build-css'], function () {
-	return merge2(embed_js, embed_css.pipe(css2js()))
-		.pipe(concat('duoshuo-ua-parser-css.js'))
-		.pipe(uglify())
-		.pipe(header(banner, {
-			pkg: pkg,
-			subtitle: 'CSS集成版',
-			description: '此版本集成ua-parser和默认CSS,提供默认的UA显示方案',
-		}))
-		.pipe(rename({suffix: '.min'}))
-		.pipe(gulp.dest('./dist'));
-});
-
-gulp.task('build', ['build-core', 'build-with-ua-parser-css']);
+gulp.task('build', ['build-js', 'build-css']);
 
 gulp.task('default', ['build']);

+ 4 - 8
package.json

@@ -5,6 +5,9 @@
   "description": "Plugin of duoshuo to show operating systems and browsers for duoshuo comments.",
   "author": "Gerald <gera2ld@163.com>",
   "license": "MIT",
+  "scripts": {
+    "build": "gulp"
+  },
   "repository": {
     "type": "git",
     "url": "git@github.com:gera2ld/duoshuo-ua.git"
@@ -14,15 +17,8 @@
   },
   "devDependencies": {
     "gulp": "^3.9.0",
-    "gulp-clone": "^1.0.0",
     "gulp-concat": "^2.6.0",
-    "gulp-css2js": "^1.0.2",
     "gulp-header": "^1.7.1",
-    "gulp-minify-css": "^1.2.1",
-    "gulp-order": "^1.1.1",
-    "gulp-rename": "^1.2.2",
-    "gulp-uglify": "^1.4.2",
-    "gulp-wrap": "^0.11.0",
-    "merge2": "^0.3.6"
+    "gulp-wrap": "^0.11.0"
   }
 }

+ 2 - 1
src/core.js

@@ -9,6 +9,7 @@
  */
 
 var _this = this;
+
 function emptyString(local) {
 	return '';
 }
@@ -39,7 +40,7 @@ function callAfter(local, args) {
 	var res = local.result;
 	var i = res.indexOf('<div class="ds-comment-header">');
 	var j = res.indexOf('</div>', i);
-	var func = duoshuoQuery.getUAString || _this.getUAString || emptyString;
+	var func = duoshuoQuery.getUAString || getUAString || emptyString;
 	local.result = res.slice(0, j) + func.call(_this, local) + res.slice(j);
 }
 

+ 0 - 17
src/default.js

@@ -1,17 +0,0 @@
-/**
- * 多说User-Agent插件默认显示方案
- * 使用轻量级的ua-parser.js解析User-Agent
- *
- * @author Gerald <gera2ld@163.com>
- */
-
-!function (window, undefined) {
-	var UAParser = window.UAParser;
-
-	window.getUAString = function (local) {
-		var agent = UAParser.parse(local.agent);
-		return '<div class="ds-os">' + UAParser.getString(agent.os) + '</div>' +
-			'<div class="ds-br">' + UAParser.getString(agent.browser) + '</div>' +
-			(local.webmaster ? '<div class=ds-webmaster>站长</div>' : '');
-	};
-}(this);

+ 11 - 3
src/ua-parser.js

@@ -3,7 +3,7 @@
 * @author Gerald <gera2ld@163.com>
 */
 
-!function (window, undefined) {
+this.UAParser = function () {
   var mapper = {
     reg: function (str, maps) {
       return str.replace(maps[0], maps[1]);
@@ -126,8 +126,16 @@
     return result;
   }
 
-  window.UAParser = {
+  return {
     parse: parse,
     getString: getString,
   };
-}(this);
+}();
+
+var getUAString = function (local) {
+  var UAParser = this.UAParser;
+  var agent = UAParser.parse(local.agent);
+  return '<div class="ds-os">' + UAParser.getString(agent.os) + '</div>' +
+    '<div class="ds-br">' + UAParser.getString(agent.browser) + '</div>' +
+    (local.webmaster ? '<div class=ds-webmaster>站长</div>' : '');
+};