aboutsummaryrefslogtreecommitdiff
path: root/guidelines/wikipedia/src
diff options
context:
space:
mode:
Diffstat (limited to 'guidelines/wikipedia/src')
-rw-r--r--guidelines/wikipedia/src/bullets.js8
-rw-r--r--guidelines/wikipedia/src/color.js90
-rw-r--r--guidelines/wikipedia/src/floatSandwiches.js29
-rw-r--r--guidelines/wikipedia/src/headingOrder.js47
-rw-r--r--guidelines/wikipedia/src/horizontalRule.js8
-rw-r--r--guidelines/wikipedia/src/imageAlt.js8
-rw-r--r--guidelines/wikipedia/src/imageCaption.js18
-rw-r--r--guidelines/wikipedia/src/imageSize.js23
-rw-r--r--guidelines/wikipedia/src/inlineStyle.js47
-rw-r--r--guidelines/wikipedia/src/layout.js7
-rw-r--r--guidelines/wikipedia/src/paragraphLength.js15
-rw-r--r--guidelines/wikipedia/src/pseudoHeadings.js14
-rw-r--r--guidelines/wikipedia/src/pseudoIndent.js10
-rw-r--r--guidelines/wikipedia/src/spaceBetweenListItems.js15
-rw-r--r--guidelines/wikipedia/src/spaceBetweenParagraphs.js28
-rw-r--r--guidelines/wikipedia/src/strikeout.js14
16 files changed, 381 insertions, 0 deletions
diff --git a/guidelines/wikipedia/src/bullets.js b/guidelines/wikipedia/src/bullets.js
new file mode 100644
index 0000000..80c5c4b
--- /dev/null
+++ b/guidelines/wikipedia/src/bullets.js
@@ -0,0 +1,8 @@
+exports.name = "Minimize use of bullet points";
+exports.description = "Bullet points should be minimized in the body and lead of the article, if they are used at all.";
+
+exports.rule = function(report) {
+ $5('#mw-content-text > ul, #mw-content-text > ol').each(function() {
+ report.warning('Minimize use of bullet points.', this);
+ });
+};
diff --git a/guidelines/wikipedia/src/color.js b/guidelines/wikipedia/src/color.js
new file mode 100644
index 0000000..b9eb31b
--- /dev/null
+++ b/guidelines/wikipedia/src/color.js
@@ -0,0 +1,90 @@
+exports.name = "Color use";
+exports.description = "Use colors that have sufficient contrast and avoid issues with common forms of color blindness.";
+
+var fc = fiveui.color;
+var AA_NORMAL = 4.5;
+var AA_BIG = 3;
+var AAA_NORMAL = 7;
+var AAA_BIG = 4.5;
+
+
+/**
+ * Compute the font size in points, assuming 96dpi.
+ */
+var fontSizePt = function(elt) {
+ var px = $(elt).css('font-size');
+ return parseInt(px) * 72 / 96;
+};
+
+var isBold = function(elt) {
+ return $(elt).css('font-weight') == 'bold';
+};
+
+/**
+ * See if the text counts as "large scale" according to the W3C:
+ * (http://www.w3.org/TR/2008/REC-WCAG20-20081211/#larger-scaledef)
+ */
+var isLargeScale = function(elt) {
+ var size = fontSizePt(elt);
+ var bld = isBold(elt);
+ return (18 <= size || (14 <= size && bld));
+};
+
+var getAARatio = function(elt) {
+ if (isLargeScale(elt)) {
+ return AA_BIG;
+ }
+ return AA_NORMAL;
+};
+
+var getAAARatio = function(elt) {
+ if (isLargeScale(elt)) {
+ return AAA_BIG;
+ }
+ return AAA_NORMAL;
+};
+
+exports.rule = function (report) {
+
+ $5('#mw-content-text *')
+ // filter for lowest level elts having non-empty text
+ .filter(function () {
+ var $this = $(this);
+ return $this.children().length === 0 && $.trim($this.text()).length > 0;
+ })
+ .filter(exceptions)
+ .each(function (i, elt) {
+ var fg = fc.colorToRGB($(this).css('color'));
+ var bg = fc.findBGColor($(this));
+ if (fg && bg) {
+ var ratio = fc.contrast(fc.luminance(fg), fc.luminance(bg));
+ if (ratio < getAARatio(elt)) {
+ report.error('Element has poor contrast: ' + ratio +
+ " ratio should be greater than " + getAARatio(elt), elt);
+ } else if (ratio < getAAARatio(elt)){
+ report.warning('Element has poor contrast: ' + ratio +
+ " ratio should be greater than " + getAAARatio(elt), elt);
+ }
+ }
+ });
+};
+
+function exceptions() {
+ var $elem = $(this);
+ return !isStandardLink($elem) &&
+ !isNavboxLink($elem);
+}
+
+function isStandardLink($elem) {
+ var standard = ['new', 'external', 'extiw'];
+ var $a = $elem.closest('a');
+ return $a.is('a') && standard.some(function(klass) {
+ return $a.hasClass(klass);
+ });
+}
+
+function isNavboxLink($elem) {
+ var $a = $elem.closest('a');
+ var $nav = $a.closest('th.navbox-group');
+ return $a.length > 0 && $nav.length > 0;
+}
diff --git a/guidelines/wikipedia/src/floatSandwiches.js b/guidelines/wikipedia/src/floatSandwiches.js
new file mode 100644
index 0000000..ecdcdba
--- /dev/null
+++ b/guidelines/wikipedia/src/floatSandwiches.js
@@ -0,0 +1,29 @@
+exports.name = "Floating content on both sides of screen";
+exports.description = "Be careful not to add images or other floating content on both sides of the screen simultaneously.";
+
+exports.rule = function(report) {
+ var $topElems = $5('#mw-content-text > *');
+ var left = floating($topElems, 'left').toArray().map($);
+ var right = floating($topElems, 'right').toArray().map($);
+
+ left.forEach(function($l) {
+ var ltop = $l.offset().top;
+ var lbottom = ltop + $l.outerHeight();
+
+ if (right.some(function($r) {
+ var rtop = $r.offset().top;
+ var rbottom = rtop + $r.outerHeight();
+
+ return (rtop > ltop && rtop < lbottom) ||
+ (rbottom > ltop && rbottom < lbottom);
+ })) {
+ report.warning('Left and right floating elements overlap vertically.', $l.get(0));
+ }
+ });
+};
+
+function floating($elems, leftOrRight) {
+ return $elems.filter(function() {
+ return $(this).css('float') === leftOrRight;
+ });
+}
diff --git a/guidelines/wikipedia/src/headingOrder.js b/guidelines/wikipedia/src/headingOrder.js
new file mode 100644
index 0000000..dfb7777
--- /dev/null
+++ b/guidelines/wikipedia/src/headingOrder.js
@@ -0,0 +1,47 @@
+/**
+ * Layout rules for Wikipedia article content
+ */
+exports.name = "Headings should be in order.";
+exports.description = "Headers should increase sequentially, or reset to a higher section level.";
+
+exports.rule = function(report) {
+ findH1s(report);
+
+ checkHeadingOrder(report);
+};
+
+/**
+ * No H1 headings should be used in the article content.
+ */
+var findH1s = function(report) {
+ $5('#mw-content-text h1').each(
+ function(idx, elt){
+ report.error("Top-level headings should not be used in article content.");
+ });
+};
+
+
+/**
+ * Check that headers increase one step at a time, or go back to the
+ * beginning (in this case, heading 2).
+ *
+ * Headers using the &lt;header&gt; tag are except from this check.
+ */
+var checkHeadingOrder = function(report) {
+ var last=1;
+
+ $5('#mw-content-text :header').each(
+ function(idx, elt){
+ // parse the level out of 'h1', 'h2', 'h3', etc.
+ var level = parseInt(elt.tagName.substring(1,2));
+
+ if (level > (last + 1)) {
+ report.error("Heading is out of order; heading level was: "+level+
+ " but last level was: "+last, elt);
+ }
+ // set the level regardless, since the error *could* be with the
+ // prior level heading, so we don't want to cause more errors
+ // erroniously:
+ last = level;
+ });
+};
diff --git a/guidelines/wikipedia/src/horizontalRule.js b/guidelines/wikipedia/src/horizontalRule.js
new file mode 100644
index 0000000..b16375d
--- /dev/null
+++ b/guidelines/wikipedia/src/horizontalRule.js
@@ -0,0 +1,8 @@
+exports.name = "Horizontal rules are deprecated";
+exports.description = "Horizontal rules (----) are deprecated.";
+
+exports.rule = function(report) {
+ $5('#mw-content-text hr').each(function(i, hr) {
+ report.warning('Remove horizontal rule.', hr);
+ });
+};
diff --git a/guidelines/wikipedia/src/imageAlt.js b/guidelines/wikipedia/src/imageAlt.js
new file mode 100644
index 0000000..c54244d
--- /dev/null
+++ b/guidelines/wikipedia/src/imageAlt.js
@@ -0,0 +1,8 @@
+exports.name = "Images should include an alt attribute";
+exports.description = "Images should include an alt attribute, even an empty one, that acts as a substitute for the image (for non-visual users).";
+
+exports.rule = function(report) {
+ $5('#mw-content-text img:not([alt])').each(function(i, img) {
+ report.warning("Image has no alt attribute.", img);
+ });
+};
diff --git a/guidelines/wikipedia/src/imageCaption.js b/guidelines/wikipedia/src/imageCaption.js
new file mode 100644
index 0000000..6212830
--- /dev/null
+++ b/guidelines/wikipedia/src/imageCaption.js
@@ -0,0 +1,18 @@
+exports.name = "Images should contain a caption";
+exports.description = "Images should contain a caption, either using the built-in image syntax or a secondary line of text.";
+
+exports.rule = function(report) {
+ $5('#mw-content-text img')
+ // Exclude small images, which are probably icons.
+ .filter(function(i, img) {
+ var $img = $(img);
+ return $img.width() > 50 || $img.height() > 50;
+ })
+ .each(function(i, img) {
+ var $parent = $(img).parents(':not(a, td, tr, .thumbimage):first');
+ var text = $.trim($parent.text());
+ if (!text) {
+ report.warning("Does this image have a caption?", img);
+ }
+ });
+};
diff --git a/guidelines/wikipedia/src/imageSize.js b/guidelines/wikipedia/src/imageSize.js
new file mode 100644
index 0000000..52b5a3e
--- /dev/null
+++ b/guidelines/wikipedia/src/imageSize.js
@@ -0,0 +1,23 @@
+exports.name = "Large image";
+exports.description = "Images should be sized for comfortable display on the smallest displays in common use.";
+
+exports.rule = function(report) {
+ $5('#mw-content-text img').each(function() {
+ var $img = $(this);
+ if ($img.width() > 400 && !centered($img) && !locationNone($img)) {
+ report.warning('Image is more than 400px wide. Consider using the "center" or "none" location options for wide images', this);
+ }
+ if ($img.height() > 500) {
+ report.warning('Image is more than 500px tall.', this);
+ }
+ });
+};
+
+// Add to prelude.
+function centered($img) {
+ return $img.closest('.center').length > 0;
+}
+
+function locationNone($img) {
+ return !centered($img) && $img.closest('.tnone').length > 0;
+}
diff --git a/guidelines/wikipedia/src/inlineStyle.js b/guidelines/wikipedia/src/inlineStyle.js
new file mode 100644
index 0000000..261586d
--- /dev/null
+++ b/guidelines/wikipedia/src/inlineStyle.js
@@ -0,0 +1,47 @@
+exports.name = "Do not use in-line styles";
+exports.description = "In-line styles make it much harder for people with specific needs to change the wikimedia styles and to retain consistency.";
+
+exports.rule = function(report) {
+ $5('#mw-content-text [style]').filter(excludes).each(function(i, elem) {
+ report.error("Element contains in-line style rules.", elem);
+ });
+};
+
+function excludes(i, elem) {
+ var $elem = $(elem);
+
+ // Ignore width rules.
+ var widthRule = everyStyle($elem, function(s) {
+ return s === 'width';
+ });
+
+ // It seems that Wikipedia's standard table templates include some
+ // inline styles. Ignore these.
+ var table = $elem.is('table, th, td');
+
+ // The standard reference list template also seems to include some
+ // inline styles.
+ var reference = $elem.hasClass('reflist references-column-width') ||
+ $elem.hasClass('error') ||
+ ($elem.is('.citation ~ * *') && !$.trim($elem.text())); // <span>&nbsp;</span>
+
+ // The [citation needed] template includes a white-space:nowrap style.
+ var citationNeeded = $elem.hasClass('Template-Fact') && everyStyle($elem, function(s) {
+ return s === 'white-space';
+ });
+
+ var navboxPadding = $elem.closest('.navbox').length > 0 && everyStyle($elem, function(s) {
+ return s.slice(0,7) === 'padding';
+ });
+
+ // Ignore hidden microformat fields.
+ var microformat = $elem.css('display') === 'none' &&
+ $elem.closest('.vcard, .vevent').length > 0;
+
+ return !widthRule && !table && !reference && !citationNeeded &&
+ !navboxPadding && !microformat;
+}
+
+function everyStyle($elem, fn) {
+ return Array.prototype.every.call($elem.prop('style'), fn);
+}
diff --git a/guidelines/wikipedia/src/layout.js b/guidelines/wikipedia/src/layout.js
new file mode 100644
index 0000000..48896fe
--- /dev/null
+++ b/guidelines/wikipedia/src/layout.js
@@ -0,0 +1,7 @@
+/**
+ * Layout rules for Wikipedia article content
+ */
+exports.name = "Layout rules for headings";
+exports.description = "";
+
+exports.rule = function(report) {};
diff --git a/guidelines/wikipedia/src/paragraphLength.js b/guidelines/wikipedia/src/paragraphLength.js
new file mode 100644
index 0000000..ba20306
--- /dev/null
+++ b/guidelines/wikipedia/src/paragraphLength.js
@@ -0,0 +1,15 @@
+exports.name = "Avoid single-sentence paragraphs";
+exports.description = "The number of single-sentence paragraphs should be minimized.";
+
+exports.rule = function(report) {
+ var sentenceBoundary = /[.?!](?:(?:\[\d+\])|['"])*(?:\s|$)/gm;
+
+ $5('#mw-content-text p').each(function(i, p) {
+ var $p = $(p);
+ var text = $.trim($p.text());
+ var boundaries = text && text.match(sentenceBoundary);
+ if (boundaries && boundaries.length === 1) {
+ report.warning('Paragraph with only one sentence: "' + text +'"', p);
+ }
+ });
+};
diff --git a/guidelines/wikipedia/src/pseudoHeadings.js b/guidelines/wikipedia/src/pseudoHeadings.js
new file mode 100644
index 0000000..bbf7d8d
--- /dev/null
+++ b/guidelines/wikipedia/src/pseudoHeadings.js
@@ -0,0 +1,14 @@
+exports.name = "Do not make pseudo-headings";
+exports.description = "Do not make pseudo-headings using bold or semicolon markup.";
+
+exports.rule = function(report) {
+ $5('#mw-content-text p > b:only-child').each(function(i, b) {
+ var text = $.trim($(b).text());
+ report.error('Bold text used as pseudo-heading: '+ text, b);
+ });
+
+ $5('#mw-content-text dl:not(:has(dd)) dt').each(function(i, dt) {
+ var text = $.trim($(dt).text());
+ report.error('Semicolon markup used to create pseudo-heading: '+ text, dt);
+ });
+};
diff --git a/guidelines/wikipedia/src/pseudoIndent.js b/guidelines/wikipedia/src/pseudoIndent.js
new file mode 100644
index 0000000..73b1700
--- /dev/null
+++ b/guidelines/wikipedia/src/pseudoIndent.js
@@ -0,0 +1,10 @@
+exports.name = "Do not use colon markup for indentation";
+exports.description = "Preceding text with a colon (:) in wiki markup causes that text to appear to be indented; but the actual result is a definition list with one item without a title.";
+
+exports.rule = function(report) {
+ $5('#mw-content-text dl:not(:has(dt)) dd').each(function(i, dd) {
+ var text = $.trim($(dd).text());
+ report.error('Colon markup used to indent text: '+ text, dd);
+ });
+};
+
diff --git a/guidelines/wikipedia/src/spaceBetweenListItems.js b/guidelines/wikipedia/src/spaceBetweenListItems.js
new file mode 100644
index 0000000..890b31c
--- /dev/null
+++ b/guidelines/wikipedia/src/spaceBetweenListItems.js
@@ -0,0 +1,15 @@
+exports.name = "Do not separate list items with blank lines";
+exports.description = "Leaving blank lines between list items causes mediawiki to end one list and to start a new one.";
+
+exports.rule = function(report) {
+ $5('ol:has(> li:only-of-type) + ol:has(> li:only-of-type)').each(reportWarning);
+ $5('ul:has(> li:only-of-type) + ul:has(> li:only-of-type)').each(reportWarning);
+
+ $5('dl:has(> dt:only-of-type):has(> dd:only-of-type) + '+
+ 'dl:has(> dt:only-of-type):has(> dd:only-of-type)').each(reportWarning);
+
+ function reportWarning(i, list) {
+ var text = $.trim($(list).text());
+ report.warning('List with a single item: '+ text, list);
+ }
+};
diff --git a/guidelines/wikipedia/src/spaceBetweenParagraphs.js b/guidelines/wikipedia/src/spaceBetweenParagraphs.js
new file mode 100644
index 0000000..ccab3a4
--- /dev/null
+++ b/guidelines/wikipedia/src/spaceBetweenParagraphs.js
@@ -0,0 +1,28 @@
+exports.name = "There should only be one blank line between paragraphs";
+exports.description = "Between sections - as between sections - there should be only a single blank line.";
+
+exports.rule = function(report) {
+ var problemPs = [];
+
+ $5('p:has(> br)').each(function(i, p) {
+ var $p = $(p), prevP;
+ if ($.trim($p.text()).length === 0) {
+ prevP = $p.prevAll('p').filter(function(i, pp) {
+ return $.trim($(pp).text()).length > 0;
+ }).first();
+
+ if (prevP.length) {
+ problemPs.push(prevP.get(0));
+ }
+ else {
+ report.error('Paragraph contains line breaks but does not contain text.', p);
+ }
+ }
+ });
+
+ _.uniq(problemPs, false).forEach(function(p) {
+ var text = $.trim($(p).text());
+ report.error('Paragraph is followed by more than one blank line: '+ text, p);
+ });
+};
+
diff --git a/guidelines/wikipedia/src/strikeout.js b/guidelines/wikipedia/src/strikeout.js
new file mode 100644
index 0000000..e1e3856
--- /dev/null
+++ b/guidelines/wikipedia/src/strikeout.js
@@ -0,0 +1,14 @@
+exports.name = "Don't use strikeout.";
+exports.description = "By default, most screen readers do not indicate presentational text attributes (bold, italic, underline) or even semantic text attributes (emphasis, importance, text deletion), so struck-out text is read normally along with any other text.";
+
+exports.rule = function (report) {
+ var err = function(idx, elt) {
+ report.error("Strikeout tags should not be used.", elt);
+ };
+
+ $5('#mw-content-text del').each(err);
+ $5('#mw-content-text strike').each(err);
+ $5('#mw-content-text span').filter(function(i, s) {
+ return (/line-through/).test($(s).css('text-decoration'));
+ }).each(err);
+};