Commit graph

557 commits

Author SHA1 Message Date
Ed Sanders 13eb918087 Only generate transclusion contents for clipboard
Parsoid doesn't care about the transclusion contents and it can
cause bugs if not removed properly. Remove the about group attribute
as that was for Parsoid's benefit.

Depends on Ib29972472d in core.

Bug: 60897
Change-Id: I907b2113c257baff5c022ff0749dca9dbb1fba5f
2014-02-05 12:45:55 -08:00
Ed Sanders bdb4a8a149 Simplify toDataElement in MW
As per I54943588c5cc2 in core.

Change-Id: Ia40e7327c4ce07a79d64a6d5b1ff0d7acec55171
2014-01-27 18:43:36 -08:00
Roan Kattouw 4aeb773404 Add tagName to ve.dm.MWGalleryNode
I told James this wasn't needed, but I was wrong. It is null in
the parent class, and DOM throws on document.createElement(null).

Bug: 60307
Change-Id: Iff8fda9acf9f37e537d7d6cf6106a801d6b71338
2014-01-27 14:28:16 -08:00
jenkins-bot 319fa24061 Merge "ve.dm.MWTransclusionModel: Clean up and fix logic error" 2014-01-23 03:00:55 +00:00
Timo Tijhof 7316c6ba3b ve.dm.MWTransclusionModel: Clean up and fix logic error
* Reduce duplication by calling #removePart (equal, line by line)
* Reset `remove` at the start of each iteration, it was leaking
  through to future iterations.
* Minor simplification in property access.

Change-Id: Ie0a83d582804bc50131ca5a8da36b0605dd4a6c3
2014-01-23 02:58:23 +00:00
Ed Sanders bb773e852c Relativise URLs against target document
mw.Uri will just be using window.document, which may have
a different base.

Depends on I86fe6c2f41e549 in core.

Bug: 58136
Change-Id: I320d5d477d97ebf25963ab2dc429931bc871dd17
2014-01-22 18:46:38 -08:00
Trevor Parscal 92746ef3da Implement 'change' events in templates models
This will make generating live previews possible.

Changes:
* Add change events to template model.
* Set up connect/disconnect.

Also:
* Add missing fallback for getParameterLabel (Param#label is
  optional per the TemplateData spec).
* Implement getWikitext, to be used by the UI dialog later
  to create a preview from the wikitext.
* Correctly mark ve.dm.MWTransclusionNode#escapeParameter as
  being a static method.

Change-Id: Ie306ed03babf11568e954b1813ce5324f57d7f0e
2014-01-22 19:03:17 +00:00
Ed Sanders fdb4062aec Remove unnecessary strangely written range clone
Probably left over from when the range calculation was more complex.

Change-Id: I59c989bac0d80f4a12e57cbd41bdc6587acd964a
2014-01-21 17:35:45 +00:00
jenkins-bot adf8249688 Merge "Ultra-basic gallery editing" 2014-01-15 23:27:06 +00:00
James D. Forrester 842688c51b Ultra-basic gallery editing
'Cos Erik doesn't like things he can't edit.

Change-Id: I1d9fb1215bb16b1245eddd87c977fb5bfdee4da9
2014-01-15 15:13:12 -08:00
jenkins-bot 6a04a92f32 Merge "Support external links in MWInternalLinkAnnotation" 2014-01-15 22:27:29 +00:00
Trevor Parscal c8f7845def Display indicators for required parameters in template dialog
Update submodule for changes in OOUI (I1c047b55c7a0d5cf3e0aa0cc3f9a4da7d45c0304)

Change-Id: I8f84a9ae277e5093356f591f7a56e8cebf4a1893
2014-01-15 14:15:21 -08:00
Ed Sanders 217ea940d5 Support external links in MWInternalLinkAnnotation
As URLs from the clipboard are always absolute, we need to detect if these
are from the same wiki as the current document, and if so convert back to
relative for Parsoid.

Bug: 58136
Change-Id: Id251afe65193fc6356628f1deb5ed757f8a6d347
2014-01-15 12:20:46 +00:00
Ed Sanders 3059fecc5f About-group extra DOM data in toDomElements
Although marked as data-ve-ignore, it isn't ignored by Parsoid,
so about group it together as well.

Bug: 59002
Change-Id: I263e316fb10f3e6f23fc1d409686cdefbd28fafa
2014-01-15 11:06:25 +00:00
jenkins-bot 2284cb9aae Merge "Factor out AJAX defaults into ve.init.mw.Target.static.apiRequest()" 2014-01-15 10:37:43 +00:00
jenkins-bot 7c087176ac Merge "Use paramOrder data for ordering template parameters" 2014-01-15 02:58:52 +00:00
Ed Sanders b2b9f217da Wrap text nodes in spans if trying to mark as data-ve-ignore
Otherwise you're going to have a bad time.

Bug: 59002
Change-Id: Ifd90087b3d36f412420b9786f3d54a5418846d03
2014-01-14 23:42:49 +00:00
Trevor Parscal 2a40b3b27b Use paramOrder data for ordering template parameters
Parameters are ordered using 2 consecutive buckets, the intersection of
paramOrder and parameters in use ordered using paramOrder followed by the
remaining parameters in alpha-numeric order.

A patch to TemplateData was needed to make this work, but we won't get a
crash without it, just no order specification:
    Ic5b42c4189868412138680654c499b6c8bc8f47e

The paramOrder property needs some help still, as it currently requires
being either omitted or containing an exhaustive list of all known
parameters. It should backfill unmentioned params in JSON specified order
instead.

Bug: 51930
Change-Id: Ic3eb665389380c8e3dd6562b059c2f6655a22588
2014-01-14 20:19:54 +00:00
Roan Kattouw 97c4c6c71b Factor out AJAX defaults into ve.init.mw.Target.static.apiRequest()
Change-Id: I90b0858ccd657b7183ae5327903449d17d9f0bef
2014-01-13 11:45:30 -08:00
Ed Sanders cd55b92bb2 Fix more copyright headers not updated to 2014
Change-Id: Ib45ae179c001ca270597ad954f65b0b1b2c776de
2014-01-13 15:08:24 +00:00
jenkins-bot 2016380ac5 Merge "Let users set __NOEDITSECTION__ status" 2014-01-06 09:45:49 +00:00
James D. Forrester 707f7c93a5 Let users set __NOEDITSECTION__ status
Adds a checkbox to the page settings pane of the meta dialog that lets
users set or unset the __NOEDITSECTION__ flag on the page.

Change-Id: If1eca58e28d214021f5f5582856e595d4d0fbc43
2014-01-06 17:42:57 +08:00
James D. Forrester 0ffd654bed Bump copyright like it's 2014
Change-Id: Ic469ebda2c061dc7da0b4c1625f43a7be55da4fa
2014-01-05 20:06:50 +08:00
James D. Forrester 0fadc2bc77 Let users set __NOTOC__ & __FORCETOC__ status
This creates a new panel in the meta dialog, "Page settings", where page-
level settings will be, err, set. For now, this exposes just the
behavioural switches for the presence/absence of the Table Of Contents –
__NOTOC__ and __FORCETOC__.

As part of this change, the meta dialog is renamed to "Options" to be
less confusing, and the icon for the meta dialog is changed to the
generic one for dialogs, which was previously unused. The page settings
pane is provided first in this list, given that the categories pane
(amongst others) is now directly accessible through the toolbar menu.

Bug: 56866
Bug: 56867
Change-Id: I33ce05c19d2e19b249e1cefd26fd0e3697d0085d
2014-01-05 18:56:53 +08:00
Ed Sanders f5cbcc4f56 Add useful HTML in toDomElements for refs and templates.
For the benefit of pasting out of VE.
Use data-ve-ignore where necessary to avoid the HTML being
used on the way back in to VE.

Change-Id: Iabe678c4246c1d1f51abb058b6e750811fdf9bea
2013-12-16 14:33:40 +00:00
Ed Sanders 8ce7182045 Move index label generation to the model
Also make available as a static method so it can be used by the
converter. We will need this for generated HTML for the external
clipboard.

Change-Id: Ief843ac10cd6c6e4b25e09a007625d363792adff
2013-12-14 00:02:50 +00:00
Ed Sanders 2843714834 Fix hashes in MW toDomElement functions
Hashes weren't using the new [ object, config ] set up so were
never matching the store. Also added a check to see if the
originalDomElements actually exists before trying to use them
(they may have been removed by a clone operation).

Change-Id: I886e369ced9a9d2e0e457ced9c21b2a7a8e55d58
2013-12-13 17:48:03 +00:00
Ed Sanders f0e9ec7922 Fix issues with copy-pasting MWTransclusionNodes
ve.dm.MWTransclusionNode
* Implement getClonedElement to remove originalDomElements
  and originalMw. We don't want to put these in the clipboard
  as there is no guarantee they are the rendering of the current
  set of parameters (a refresh may be in progress) and they may
  confuse the converter on the way back in.
  Remove about attribute to prevent about grouping of duplicated
  nodes.
* Set an extra attribute to flag that the outputted DOM doesn't
  have any generated content attached to it that can be stored
  on load.
* Check for said attribute in toDataElement and skip the
  storeGeneratedContents step. This will trigger an async update
  of the generated contents on paste.

ve.ce.Surface
* Call cloneElements before writing to pasteTarget so data in external
  clipboard is stripped of generated contents.

ve.dm.Node
* Only strip data-parsoid as other attributes may be meaningful.

ve.dm.mwExample, ve.dm.Node.test
* Update tests

Bug: 58241
Change-Id: I3e15cc97e94747647078204a0b398e6ac3ec6382
2013-12-12 00:02:11 +00:00
jenkins-bot 47fcb0fad1 Merge "Revert "Revert "Remove dual-type support for Languages and Categories""" 2013-12-06 21:15:40 +00:00
Catrope c3c0a5e166 Revert "Revert "Remove dual-type support for Languages and Categories""
The Parsoid team says the cache is clean of old language /
category types, and would like us to use the new types
for newly generates languages/categories.

This reverts commit d8dcafe25b.

Change-Id: I0cffd5d299624230f3805f9468b2497f392c12c0
2013-12-06 21:12:44 +00:00
Timo Tijhof cf7f2b141d Set up node-jscs, pass it, and configure in local Gruntfile
Let's experiment with this via our local Gruntfile. If it works
fine we can install it in Jenkins (similar to node-csslint).

Verify through $ npm install && npm test;

Fixed all outstanding violations.

Also:
* Added syntaxhighight to ignore.
* Added imetests (which contain unformatted JSON) to ignore.
* In ve.dm.ModelRegistry#matchTypeRegExps, removed redundant
  !! cast from the [+!!withFunc] statement which was hitting
  a bug in node-jscs. All callers to this local private function
  pass a literal boolean true/false so no need to cast it.
* Removed "/* key .. , value */" from ve.setProp, though this
  wasn't caught by node-jscs, found it when searching for " , ".
* Made npm.devDependencies fixed instead of using tilde-ranges.
  This too often leads to strange bugs or sudden changes. Fixed
  them at the version they were currently ranging to.

Bug: 54218
Change-Id: Ib2630806f3946874c8b01e58cf171df83a28da29
2013-12-06 10:37:27 -08:00
jenkins-bot d17e031d46 Merge "Revert "Remove dual-type support for Languages and Categories"" 2013-12-06 04:03:10 +00:00
Jforrester d8dcafe25b Revert "Remove dual-type support for Languages and Categories"
'Cos Parsoid caches things for ages.

This reverts commit 114a24f1d3.

Change-Id: I8b2f4d982becea36ddc06b29b3a48660fa0f3a44
2013-12-06 04:01:00 +00:00
jenkins-bot 674236cab4 Merge changes I51e74b32,Ibaa14d20
* changes:
  Refactor Transclusion and Meta dialogs to use BookletLayout
  Update OOJS UI to v0.1.0-pre (592e1d6401)
2013-12-06 00:48:41 +00:00
Trevor Parscal 51e096d6f2 Refactor Transclusion and Meta dialogs to use BookletLayout
Use OOJS-UI's newly-extended paged dialogs (in e08eb2a03b) to refactor
how the Transclusion and Meta dialogs work, splitting out the code for
each of the panels into its own file and simplifying extensibility.

The Meta dialog (ve.ui.MWMetaDialog) now has two self-managing panels:
* ve.ui.MWCategoriesPage for categories and the default sort key
* ve.ui.MWLanguagesPage for language links

The Transclusion dialog (ve.ui.MWTransclusionDialog) now has four:
* ve.ui.MWTemplatePage for a template's primary panel
* ve.ui.MWTemplateParameterPage for each parameter of a template
* ve.ui.MWTemplatePlaceholderPage for a placeholder to insert a template
* ve.ui.MWTransclusionContentPage for non-template transclusion

Additionally, the Transclusion dialog has been slightly cleaned up:
* Replace add/remove events with replace events in transclusion model
* Actually return and resolve a promise (as documented)
* Get rid of "origin" info in template models
* Add method for adding required parts

TODO:

* Decide how and when we will choose between advanced transclusion and
  template dialogs
* Work out design issues with how template descriptions will be visible
  and how adding parameters will work if only showing parameters in
  outline
* Add preview to template dialog
* Consider ways to further improve pages for use in continuous mode

WARNING:

* Right now the template dialog gets overridden by the advanced
  transclusion dialog because they have the same symbolic name and the
  latter is registered later than the former. To test the template
  dialog, just change the symbolic name of the advanced transclusion
  dialog.

Change-Id: I51e74b322aec9a4c3918e6f792bdb3d318060979
2013-12-05 16:26:26 -08:00
jenkins-bot 68ad762613 Merge "Remove dual-type support for Languages and Categories" 2013-12-05 23:01:32 +00:00
Ed Sanders 3c66a297c9 Merge getDataFromDom and getModelFromDom
Now getDataFromDom is no longer called externally, we can merge these two
methods to provide one API endpoint. Also now we have deleted getDataFromDom
we can remove the 'Recursion' disambiguator from the internal function.

Also now that the whitespace info doesn't need to be passed around, implement
it as a simple return value get function.

Change-Id: I9c667e9b90443d12660b731347d7535ccb1a17cd
2013-12-05 21:54:08 +00:00
James D. Forrester 114a24f1d3 Remove dual-type support for Languages and Categories
The new form was implemented in Parsoid and deployed in October, so enough time
has passed that there is no longer any need for VisualEditor to support the old
type.

Bug: 56009
Change-Id: Ief2e584345ccdb0e7eb44ab16c4bc14f7c14f5ec
2013-12-04 18:49:48 -08:00
Ed Sanders 7cec9ae04a Rich paste
Allow pasting of rich (HTML) content.

ve.ce.Surface
* Use a sliced document clone for converting to DM HTML (copy)
* Add full context to pasteTarget before copying
* Add ve-pasteProtect class to spans to prevent them being dropped
* Implement external paste by converting HTML to data and inserting
  with newFromDocumentInsertion
* Remove clipboard key placeholder after read so they aren't picked
  up by rich paste. Hash no longer includes the placeholder.
* Detect the corruption of important spans and fallback to clipboard
  data HTML if available.

ve.dm.LinearData
* Add clone method for copy

ve.dm.ElementLinearData
* Add compareUnannotated for use by context diffing.
* Add sanitize method for cleaning data according to a set of rules.

ve.dm.Transaction
* Add range parameter for inserting a range of a document only,
  e.g. stripping the paste context.

ve.dm.Document
* Implement sliced document clone creation so that DM HTML
  is generated correctly in onCopy

ve.dm.DocumentSlice
* Replaces LinearDataSlice. Now has two ranges for balanced data
  and data with a full context.

ve.init.Target.js
* Define default, loose, paste rules (just remove aliens).

ve.init.mw.ViewPageTarget
* Define strict MW paste rules:
  + no links, spans, underlines
  + no images, divs, aliens
  + strip extra HTML attribues

ve.init.sa.Target, ve.init.mw.ViewPageTarget, ve.ui.Surface
* Pass through and store paste rules.

Bug: 41193
Bug: 48170
Bug: 50128
Bug: 53828
Change-Id: I38d63e31ee3e3ee11707e3fffed5174e1d633b42
2013-11-26 18:23:12 +00:00
Roan Kattouw cde3304864 Recompute auto-numbered reference listKeys when merging internalLists
This fixes some of the problems with pasting references.

It's a bit overzealous in that references get renumbered even when
replacing, which is unnecessary but doesn't actually have any
noticeable effect.

Unfortunately, the internal list state depends so much on the converter
having run that we now need to add yet another hack, to set the counter
to the appropriate value.

Change-Id: I3c6514ce600af4f4c037f419554d34b5a5c86a63
2013-11-20 16:50:48 +05:30
jenkins-bot 457cbfdbe8 Merge "Prevent link-annotating MWReferences" 2013-11-19 11:01:40 +00:00
Ed Sanders f9d7129465 Prevent link-annotating MWReferences
As it isn't sensible wikitext.

Bug: 56250
Change-Id: I7ec03f87ad69645c2877ee7a399950f3967a1362
2013-11-19 10:58:20 +00:00
Timo Tijhof 4854d644ee doc: Get rid of 'static' property container in jsduck index
Us grouping the inheritable static properties that way is an
implementation detail that is polluting the index and makes
it harder to refer to individual identifiers.

It also causes problems under JSDuck 5 because that version is
more strict about defining properties (Foo.static.bar) of which
the parent is not defined in the index (Foo.static), we'd have
to add a sea of `@static @property {Object} this.static` all
over the place. Might as well hide this implementation detail
and just consider them static properties (just like we already
do for "private" properties).

Change-Id: Ibf2ebf7752aabc2b75b6ac6fa00e2284a181a600
2013-11-19 10:21:39 +00:00
Trevor Parscal 2d7f93bdb6 Make generic localization utility for lang code keyed objects
Utilize in OO.ui.IconedElement and ve.dm.TemplateSpecModel

Change-Id: I0883a73cb478d4f7509f61aebed2b2957ddb9ce8
2013-11-13 14:26:51 -08:00
Roan Kattouw 3ed7bb16a6 Send the old category and language types to Parsoid for back compat
Change-Id: If67d822e1a22bc24aa0c816952081dc614f6e686
2013-11-04 19:41:19 -08:00
Timo Tijhof 44ada9ac71 dm.MWTemplateSpecModel: Resolve translations through the TemplateData API
Also removed comment in ui.MWTransclusionDialog that was
copied from dm.MWTemplateSpecModel.

Bug: 50888
Change-Id: I9dcfef3ae65fe716bae91f703f9169171448797a
2013-10-31 00:54:59 +00:00
Roan Kattouw 5c04118c07 Get rid of dmRendering hack in ve.ce.MWInternalLinkAnnotation
Centralize href computation in getHref(). Because getHref() is provided
by the generic LinkAnnotation class, the subclass implementation is
now simpler.

Bug: 51487
Change-Id: Ia6ca85bc84b4f4453b572285836adb631e8d0683
2013-10-28 15:49:08 +00:00
Roan Kattouw 74b8807df5 Resolve rendered URLs according to the provided <base>
This is done by using the computed property value rather than the
literal attribute value when rendering href and src attributes.
Helpfully, this provides perfect URL resolution natively in the browser,
which means the document's <base> is respected and all that good stuff.

For GeneratedContentNodes, we also need to find all DOM elements inside
the rendered DOM that have href or src attributes and resolve those.
This is done in the new getRenderedDomElements() function, which the
existing cleanup steps (remove <link>/<meta>/<style>, clone for
correct document) were moved into.

In order to make sure that the computed values are always computed
correctly, we need to make sure that in cases where HTML strings
in data-mw are parsed, they're parsed in the context of the correct
document so the correct <base> is applied.

We still need to solve this problem for models that actually store and
edit an href or src as an attribute. I'll post more about that on
bug 48915.

Bug: 48915
Change-Id: Iaccb9e3fc05cd151a0f5e632c8d3bd3568735309
2013-10-28 15:16:05 +00:00
jenkins-bot a07f270fc5 Merge "Don't corrupt categories/langlinks with new types" 2013-10-28 12:34:00 +00:00
Timo Tijhof 6560cfda2b Remove simpleArray utilities from ve.js and use oojs instead
Change-Id: I23710ff50378f4069b8a0dea89f0491884acd377
2013-10-23 03:26:53 +02:00
Trevor Parscal b635541de2 Remove ve.getHash and use getHash from oojs instead
Change-Id: Ib688a3ba0ab07e0d0dc328a3878440756d1103fe
2013-10-22 19:14:23 +00:00
Timo Tijhof 7db65f386c Rename @emits to @fires so we're forward compatible with JSDuck 5
Instead of using @emits in both, use our custom @fires in
production (JSDuck 4), and in the future it'll just naturally
use the native one.

This way we can also index oojs without issues, which seems to
have started using @fires already.

Change-Id: I7c3b56dd112626d57fa87ab995d205fb782a0149
2013-10-22 19:11:16 +00:00
Trevor Parscal 6018e77d70 Use OO.EventEmitter instead of ve.EventEmitter
Change-Id: Ie35e5f51a8d3c0d7f4fa46230b7b37112df610b9
2013-10-22 16:57:33 +00:00
Roan Kattouw d3c706ff93 Add a node type for numbered external links
Since I0f0a826c in Parsoid, numbered external links are now empty
<a rel="mw:ExtLink"></a> tags. This means we have to put in a node type
for them to prevent them from being considered empty annotations and
getting converted to alienMeta.

MWNumberedExternalLinkNode is protected and focusable to avoid making
the link text (which isn't editable) clickable. It isn't inspectable
yet, we need to work on that.

Bug: 53505
Change-Id: I83f69695f3974089e51a84e799f31ab6ed879e05
2013-10-18 22:31:45 +02:00
Trevor Parscal efafed3231 Remove ve.{inheritClass,mixinClass} and use OO instead
Change-Id: I8df9226a358a76b661eab6e967ff0d63d361f691
2013-10-18 18:58:08 +02:00
Timo Tijhof 832f8e1e11 Document constructor params for dm.MWMathNode and dm.MWExtensionNode
Follows-up Ib909c5fb02.

Change-Id: Ia3dfbabc8dde9f1e65e8fbb0e4d67f868031247a
2013-10-18 12:44:50 +00:00
Roan Kattouw 660e7c664a Don't corrupt categories/langlinks with new types
Parsoid changed these types from mw:WikiLink/{Category,Language}
to mw:PageProp/{Category,Language} in I0f0a826c. We had previously
added support for them in 4d91e4ed but code overwrote the new types
with the old ones on the way out, triggering the DOM corruption warning.

Change-Id: I768ec2ffd623e5a01f18959277786697603a97f0
2013-10-17 15:48:37 +02:00
Ed Sanders 8a40585847 Re-render images after resize
Using the MW APIs get a resized version of the image and use
GeneratedContentNode to cache the url.

Bug: 55697
Change-Id: I418f7e1464663f447d46de7ffc29aa5f52d23b12
2013-10-16 16:38:31 +01:00
Ed Sanders a1a448b6de Rename storeDomElements to storeGeneratedContents
The default is to store the entire generated DOM node, but in
general classes can store anything that can be held by the store.

Change-Id: Ia761079fadfb5a6cfa2f00e5b5e23d6c6d3468ac
2013-10-16 11:17:01 +01:00
Ed Sanders c7b3d34017 Convert MWBlockImage dimensions to numbers and update tests
MWInlineImage already does this but it wasn't copied over to
MWBlockImage.

Change-Id: I9f34182b30ae72beb7b5c3d5fde2f08185cba663
2013-10-15 17:59:39 +01:00
Timo Tijhof eb515188ec Convert try/catch uses of mw.Title to newFromText
`new mw.Title` throws on invalid input. Converting uses to
mw.Title.newFromText instead and converting try/catch to if/else.

mw.Title in general (regardless of which constructor) has been
improved in core. It will no longer crash on pages where the page
title was a false hit for invalid (e.g. we couldn't load VE on
[[.com]] because the js parser thought it was invalid).

However, though the initialisation works since core has been
fixed, there are still plently of cases where we take real user
input that can genuinely be invalid.

In cases where the code did not catch exceptions and there was
no obvious way to handle it, I left it as is (let's revisit them
in a separate commit). It would be an exception either way, and
I'd rather see "mw.Title: Parser error" than
"TypeError: null does not have method getNamespaceId".

Change-Id: I5b1b23d56d39cdb7ecb0809e3d721992e0c30f54
2013-10-09 21:21:25 +00:00
jenkins-bot 9740d1683e Merge changes I9e065aa4,Iac7649f4
* changes:
  MW*ImageNode's can't take link annotations
  Node annotation blacklists
2013-09-24 00:09:22 +00:00
Roan Kattouw eb64743436 Prevent naming collisions when generating unique reference names
Simply generating ':3' as the "unique" name for the 4th reference
doesn't work. Even if getUniqueListKey() had been used, that only
checks for conflicts with names that have already been encountered
(i.e. occur in <ref> tags that precede the current one), not for
conflicts with names that first occur further down in the document.

The solution is to generate names at serialization time, when we
have full knowledge of which names are in use. Internally, we use
'literal/<name>' for names that literally appeared in the source,
and 'auto/<number>' for unnamed references. Then at serialization
time, we translate 'auto/<number>' to 'literal/:<number>' if needed
(i.e. if the reference was reused).

ve.dm.MWReferenceNode.js:
* toDataElement()
** Prefix listKey with literal/ or auto/ as appropriate
* toDomElements()
** Map auto/ listKeys to unique names
** Don't try to unset the name if not present (was unsetting a property
   that didn't exist anyway)

ve.dm.InternalList.js:
* Remove now-unused isUniqueListKey()
* Rewrite getUniqueListKey()
** Make prefix configurable
** Take previously generated unique keys into account
** Map the same old key (auto/N) to the same generated key (literal/:M)
* Add getNextUniqueNumber() as a source for auto/N numbers: previously
  used the length of the itemHtmlQueue, but that only works during
  conversion, not from the UI dialog

ve.ui.MWReferenceDialog.js:
* For new references or conflicting names, generate an auto/N key and
  let toDomElements() deal with actually mapping that to name

ve.dm.InternalList.test.js:
* Rename listKeys to new style
* Split the test case into two groups so we can test multi-group cases
* Add tests for getUniqueListKey()

ve.dm.mwExample.js:
* Rename things to new style
* Modify the test case so it attempts to trigger bug 54341

Bug: 54341
Change-Id: I726fb83e6fb66ffec643d996768a854ec9474b3d
2013-09-19 21:03:15 -07:00
Ed Sanders 2d0bf61c78 MW*ImageNode's can't take link annotations
Because there's no sane wikitext to handle that case, and Parsoid
will just output garbage.

Bug: 53151
Change-Id: I9e065aa46d88f6bed9c47127b3e002ec2e1fec5a
2013-09-19 19:09:28 +01:00
Roan Kattouw 9fed6b17b1 Always use multi-part format for transclusions
The Parsoid team has changed their spec to always use multi-part
format even for one-part transclusions. This commit changes VE's
output format to always be multi-part, but still accepts single-part
format on the way in.

Change-Id: I6b3156b0b599ad042bb52d7f53dcdeb1c4a0954a
2013-09-17 17:05:01 -07:00
Inez Korczyński 988f518ced Define RDFa types in ve.dm.MWInlineImageNode once and reuse whenever possible
Change-Id: I62ec12a6b71b60b15a4200722b8963d4cfd1b582
2013-09-09 13:04:08 -07:00
David Chan 8a2b55321c docs: Minor improvements
CODING.md
* Document the procedure for adding a new javascript class

ve.dm.MWExternalLinkAnnotation.js
ve.dm.MWInternalLinkAnnotation.js
ve.dm.ElementLinearData.js
ve.dm.LinearData.js
* Add whitespace line before preformatted code to fix a
  rendering bug

Change-Id: I54443ea3d4799328655d279f379d4ddc176c50a0
2013-09-05 23:56:59 +00:00
Inez Korczyński 7f9fa4f0e5 Define RDFa types in ve.dm.MWBlockImageNode once and reuse whenever possible
Change-Id: Iebb2081dee4555f459adaa4cb9b802c283cf4827
2013-09-05 15:52:07 -07:00
Ed Sanders 9ab79330c7 Round trip alien extensions correctly when edited
ce.MWExtensionNode
* Build up the wikitext for round-tripping using jQuery, and pass
  through the attributes from data-mw

dm.MWExtensionNode
* Use a static getExtensionName to correctly get the extension
  name from the dataElement (as the getMatchRdfaTypes hack won't
  work for MWAlienExtensionNode's)

dm.MWAlienExtensionNode
* Implement new static getExtensionName function

Bug: 53543
Change-Id: Id4e83c14ec68c3b3970d05317477f19aaf31abe4
2013-08-30 16:43:50 -07:00
jenkins-bot 0cdcf2d155 Merge "Always give references names. Ignore if used once." 2013-08-29 18:26:04 +00:00
Roan Kattouw 4d91e4edbf Add dual detection for types that Parsoid is about to rename
Bug: 53432
Change-Id: If404585f9a118b4155ceb46fbe8e467b41ec6b29
2013-08-28 16:30:20 -07:00
Ed Sanders 52de8b76ec Always give references names. Ignore if used once.
This avoids problems when unnamed references were copy-pasted.

Knowing that key is always non-null simplifies a lot of logic
elsewhere.

Bug: 53365
Change-Id: I3a23123ae732d9583814d38dd880a0cdf691fd5d
2013-08-28 12:47:33 -07:00
Ed Sanders 069b757afc Implement fallback langauges
Return an array of languages instead of a single language. Languages
containing hyphens return themselves along with the root code e.g.
'en-GB' => ['en-GB', 'en']

Change-Id: I840b689d0021d865f93d16d075473a2ed0a9f0d8
2013-08-20 20:12:46 +00:00
Ed Sanders 708d8b5e67 Build link-less images with <span> not <a>
toDataElement part fixed in  I6d496f7. This fixes the
toDomElement part so we don't trigger a round trip warning.

Bug: 51963
Change-Id: I27a7579890d669a8b980710db1bafe066b744236
2013-08-16 20:03:46 +01:00
Ed Sanders 67f09a0318 Fix traversal for images with link=''
We were assuming images were wrapped in <a> tags. Images with
link='' are only <span> wrapped.

Bug: 51963
Change-Id: I6d496f719cfbbc7556c55f0a660cb192040f29de
2013-08-15 20:36:49 +01:00
Ed Sanders 6fb65ec3a1 Fix MWAlienExtensionNode's extensionName in ce update
Create getter for extensionsName which is overriden by
MWAlienExtensionNode.

Also removed angle brackets around Alien title as the inspector
already has an angle bracket icon, and a '<' close button.

Change-Id: Ice8c5d73ed621f8e585b5f372788666f8c5aeb50
2013-08-15 10:40:58 +01:00
Ed Sanders ad3a7c95c8 Alien extensions
VisualEditor.i18n.php, VisualEditor.php
* Button title
* New experimental files

ve.*.MWAlienExtensionNode.js
* Very basic extension of ve.*.MWExtensionNode

ve.ui.MWAlienExtensionInspector.js
* Default to inline-block for wrapper. Should probably
  get rid of styled wrappers for GeneratedContent eventually.

ve.ui.MWAlienExtensionInspector.js
* Basic extension of MWExtensionInspector. Override title to
  use tag name e.g. '<easytimeline>'. Could be changed in future
  to 'Extension: easytimeline' or similar.

*.png, *.svg, *Icons*.css, ve.ui.MWAlienExtensionButtonTool.js
* Angle bracket icon for button (open to suggestions)

ve.ui.MWInspector.css
* Make extension inspector text input tall by default.

Change-Id: I07f0686839192cad3cd8dfd3233ae907fe5cdf6a
2013-08-08 14:27:49 +08:00
jenkins-bot 32734767fc Merge "clean up: Consistently use MW instead of Mw in constructor names" 2013-08-07 10:29:03 +00:00
Timo Tijhof eb0eeb240a clean up: Consistently use MW instead of Mw in constructor names
Most of 'em already do. Fixed the remaining ones.

Change-Id: I1a7ccb27dd66a33265dcaddaa7d34953d328ff87
2013-08-07 17:46:01 +08:00
Ed Sanders 0d1617a627 Hieroglyphics support
Mostly as a demonstration of how easy this is with MWExtensionNode.

The icon was chosen with the following criteria:
1. Recognisable (the ankh is quite common in popular culture, right?)
2. Doesn't look idiotic to academics (I've consulted an Egyptology
   PhD and they can confirm it's not the glyph for penis)
3. Renders well at <16x16

That said it does look a little like a stick man...

Bug: 43118

Change-Id: I9f9e8af501401866bfeecf0eec3690a705fbd4db
2013-08-07 09:43:04 +00:00
Ed Sanders 671c7d3b25 Create base MWExtensionNode for simple extension support
MWMath and other simple extensions all behave in a similar way, e.g.
<tagname>Foreign syntax</tagname>.

This creates a base class that should make supporting such extensions,
and editing their contents in a plain text box, very simple.

Change-Id: Icc0acb33fe32704f71dacb552d9dfa3142eaef2b
2013-08-07 17:39:31 +08:00
Ed Sanders 8c77b802b3 MWMath: Fix broken usage of old ve.copyArray method
Was missed or conflicted during the migration to ve.copy.

Change-Id: I2bb528212043a1be65ca9ae5b514981e18749fa2
2013-08-03 13:13:47 +00:00
Timo Tijhof ac6c4da3a7 doc: @return -> @returns
Follows-up 8f05cdbf70.

Change-Id: Id2b68e521ab68862f0f635925708a35d10795342
2013-08-01 02:10:23 +02:00
Timo Tijhof 8f05cdbf70 doc: Add placeholders for unindexed methods
Not having a description yet is fine, but they should at least
be indexed as blocks so that they are searchable and listed
in the jsduck generated pages. jsduck defaults to @method + name
of prototype property. And it even guesses parameters sometimes.

Search: \n\n([a-zA-Z\.]+\.prototype\.[a-zA-Z]+)
Where: modules/ve,modules/ve-mw
Where-Not: modules/ve/test
Replace: \n\n/** */\n$1

Added @return in a few places where it was easy to add.

Change-Id: I830c94cc7dbc261bd7a077391f930cbfff165f9d
2013-07-31 23:00:30 +00:00
Ed Sanders 0d30e1e77d MWMath cleanup
VisualEditor.php
* Add CSS file

ve.ce.MWMathNode.js
* Wrap the image in a span, so GenerateContentNode doesn't
  try to nest an image inside an image
* Remove unnecessary attribute setting
* Only pass unwrapped image to deferred.resolve
* Retrigger MathJax rendering

ve.ce.Node.css
* Use inline-block for image wrapper

ve.dm.MWMathNode.js
* Mixin GeneratedContentNode and implement getHash
* Copy over functionality of MWTransclusionNode:
  + Just store data-mw for attributes
  + Store orignal(DomElement|MW|Index) for selser

ve.init.mw.ViewPageTarget.js
* Add mwMath to the toolbar

ve.ui.MWMathInspector.js
* Remove static.InputWidget, not required in this architecture
* Use multiline TextInputWidget
* Only update mw attribute
* Allow creation of new math nodes

ve.ui.MWInspector.css
* Set height of TextInputWidget

Change-Id: I520f8ccc9f89a2ce70aa1d9e02ed0c6cacbecc2f
2013-07-30 23:47:37 +01:00
Roan Kattouw ed4b9c3cf0 Remove the DM 'about' attribute from references and reference lists
It's totally unnecessary, and actually caused a bug where new references
got about="undefined", which caused Parsoid to about-group adjacent
new references together.

Bug: 52228
Change-Id: Id40d53c72a35412d612ae9441ae3d561622c1bec
2013-07-30 15:08:19 -07:00
jenkins-bot 19c9be5d4f Merge "Ref in references support" 2013-07-30 21:53:00 +00:00
Ed Sanders 6d921067d7 Ref in references support
When we encounter a ref tag inside the mw-data of a references
tag, we pass it off to the converter and store it as nested data.

In toDomElements we convert any nested children and write them
back to mw-data if changed.

As refs in references are invisible we exclude them when generating
the references list in ve.ce.MWReferenceListNode.

Bug: 51741
Change-Id: I31d06616849a00449df0fc77f3b33e46207cdc7f
2013-07-30 15:41:48 +01:00
Timo Tijhof 44623c9b2a ve.copy: Remove obsolete copyArray and copyObject
These have been pointing to the same method for a while now,
we can safely remove these obsolete aliases and just use it
as generic copy.

* Each file touched by my editor had its new line at EOF fixed
  where absent
* Don't copy an otherwise unused empty object
  (ve.dm.Converter)
* Use common ve#copy syntax instead to create a link
  (ve.dm.Document, ve.dm.example)
* Remove redundant conditionals for isArray/copyArray/copyObject
  (ve.dm.example)

Change-Id: If560e658dc1fb59bf01f702c97e3e82a50a8a255
2013-07-30 01:44:22 +02:00
Timo Tijhof 08610a4ecb doc: Clean up spacing that caused <pre> or broken <ul>/<ol>
Whenever there is more than 2 spaces (except the extra space
on a continued line of an @ tag, or the extra space on a
continued line of a list item) it causes a <pre> context.

Removed both spurious spaces that caused a <pre> and ones that
didn't but looked like it could.

When making an ordered or unordered list, the first item needs
to be on a new line and in block context (e.g. an empty line
before it). Otherwise it is rendered inline as 1. Foo 2. Bar
(such as in #rebuildNodes where both the ordered and unordered
lists were broken).

Change-Id: Id0f154854afbdc8e5a8387da92e6b2cdf0875f69
2013-07-25 04:02:50 +02:00
Ed Sanders cdfed7039f Handle meta-only transclusions as meta items
To achieve this we need to evaluate the DOM contents of
transclusion nodes to see if it consists solely of meta items
and whitespace.

To check for meta items we do a model registry match, but with an
additional parameter to exclude mwTransclusion types as a possible
result (as the first item may be a meta tag, but with a mw:Transclusion
typeof attribute).

Bug: 51322
Change-Id: I89a220350fb7e10e15f3682d21438539196a5846
2013-07-24 14:27:24 +00:00
jenkins-bot 21e47c5a33 Merge changes I2edc46b6,Iea905f2b,Ia572fd06,Id81da87b,I98a7d3eb
* changes:
  Add a node class for mw:Nowiki
  Move getHashObject() from dm.Node up into dm.Model
  Allow annotations to render nothing
  Pass child DOM elements to annotations' toDomElements()
  Process annotations bottom-up rather than top-down in data->DOM
2013-07-19 19:11:38 +00:00
Roan Kattouw 7294c65a2e Add a node class for mw:Nowiki
These represent <nowiki> tags. If the user doesn't edit the text inside
the nowiki, we round-trip the <span typeof="mw:Nowiki"> wrapper cleanly,
but if they do edit it, we unwrap it. This then triggers re-escaping
in Parsoid, and prevents cases where the user edits the text to no
longer need escaping but Parsoid still wraps it in <nowiki> because
of the <span typeof="mw:Nowiki"> wrapper.

In order to detect whether the contents have changed, the nowiki
annotation stores a copy of its contents. To avoid infinite recursion,
we have to exclude this attribute for hash generation.

Bug: 47678
Change-Id: I2edc46b6d87d2f91e952efcb09c0edae5166958f
2013-07-16 19:35:24 -07:00
Ed Sanders 56ef8cb5b5 Create MWResizeableNode mixin to control defaultSize flag
Previously wasn't being updated to 'false' after a width/height
attribute change.

Bug: 50645
Change-Id: Id5dcd6998e0125757238426f8052505d131d712d
2013-07-16 23:13:40 +01:00
Trevor Parscal d3df2a5a91 Fix uses of addPart to make them async friendly
Problem:

Adding or moving templates or content resulted in the incorrect item
being selected.

Diagnosis:

Although recently we solved a few issues by making addPart async, it
caused some other issues where callers of addPart were assuming
otherwise

Solution:

Return a promise from addPart which is resolved after the part is
actually added and setup callers to use the promise when needed

Changes:

ve.ui.MWTransclusionDialog.js
* Use promises to auto-select new or moved parts

ve.dm.MWTranclusionModel.js
* Make addPart return a promise
* Resolve promise when queue is processed
* Automatically remove existing items before adding them in different
  locations at the time of processing the queue we don't yield between
  removing and adding

Change-Id: Ie43c5b89ca4ed34d5f797714e19c9a7e1824cdec
2013-07-12 01:30:04 +00:00
Trevor Parscal b3b2d3fb91 Preserve unused Parsoid template properties
Problem:

Parsoid has a property called "i" which we don't use, but they need for
round-tripping purposes. Since we were generating a structure from
Parsoid data and then generating data from the structure without
preserving properties we didn't use, it was getting lost.

Solution:

Abstract creating a template from data vs. creating it from name. Make
only templates have an origin argument in their constructors, so and
set it within a set of static constructors that create a template for
either data or a template name. Store the original data in the former
case, and use it as a base when serializing.

Changes:

ve.ui.MWTranslcusionDialog.js
* Remove no-longer-needed mw global declaration
* Move most of the addTemplate function to a static constructor in the
  template model class

ve.dm.MWTransclusionPartModel.js,
ve.dm.MWTransclusionContentModel.js,
ve.dm.MWTemplatePlaceholder
* Remove unused origin argument/property/getter
* Add serialize method (if needed)

ve.dm.MWTranclusionModel.js
* Move template/parameter generation from data into static constructor
  of template model
* Move serialization to part classes

ve.dm.MWTemplateModel.js
* Add mw global declaration
* Stop passing origin to parent constructor, store it locally instead
* Add original data property/setter for preserving unused properties
  when round tripping
* Add static constructors for generating a template from data or by name
* Add serialize method

Bug: 51150
Change-Id: Ide596a0ca0ae8f93ffce6e79b7234a1db7e0586c
2013-07-12 00:47:01 +00:00
jenkins-bot 33e653aa7e Merge "Don't change edited transclusion nodes to <span>s" 2013-07-11 22:44:14 +00:00
jenkins-bot 20da0c23a8 Merge "Auto-add required params for user added templates" 2013-07-11 16:33:52 +00:00
Trevor Parscal fc95029b34 Auto-add required params for user added templates
Objectives:

* Automatically add required parameters to templates that users create
  using the GUI, without touching existing templates loaded from data
* Cleanup some confusing terminology and APIs

Changes:

ve.ui.MWParameterSearchWidget.js
* Remove special logic for skipping aliases, which are no longer included
  in the list of names given by getParameterNames

ve.ui.MWTransclusionDialog.js
* Add origin arguments to constructors of transclusion parts
* Re-use onAddParameter method during initial construction of parameter
  pages
* Add required template parameters for user created template parts

ve.dm.MWTransclusionPartModel.js
* Add origin argument/property/getter for tracking where a part came from

ve.dm.MWTransclusionContentModel.js,
ve.dm.MWTransclusionPlaceholderModel.js,
ve.dm.MWTemplateModel.js
* Add origin argument pass through

ve.dm.MWTranclusionModel.js
* Add origin arguments to constructors of transclusion parts

ve.dm.MWTemplateSpecModel.js
* Rename origin to name - was a bad name to start with and will be even
  more confusing with the new part origin property
* Add isParameterAlias method
* Make getParameterNames only return primary names, excluding aliases

ve.dm.MWTemplateModel.js
* Update use of parameter origin, now called name

Bug: 50747
Change-Id: Ib444f0f5a8168cd59ea52a6000ba5e42ccdc2a24
2013-07-11 16:31:51 +00:00
Ed Sanders 176025e5fd Prevent escaping of piped links in wikitext parameters
Also in this commit is a fix to the regex for brackets in general
as previously it was grouping multiple pairs together which was
making the stack count incorrect.

Bug: 50801
Change-Id: I2cd825eaa7242e37a6317286cb8f9a4a78e693e2
2013-07-11 16:20:39 +01:00
Roan Kattouw a16e3fd244 Don't change edited transclusion nodes to <span>s
This is harmful because we don't know whether <span> is acceptable
in context. They're not allowed in <tbody> for instance, and so if
we replace a <tr> with a <span> that breaks things.

Instead, use the nodeName of the first original DOM element.

Change-Id: I95ea9f13985767123f692706c6cc71fefd74d517
2013-07-10 19:11:07 -07:00
Trevor Parscal 0c3ca665d2 Retain original param names and ignore leading/trailing whitespace
Objectives:

* Trim leading or trailing whitespace that parsoid may have left on
  parameter names
* Preserve the original name for round-tripping cleanliness
* Ignore leading or trailing whitespace when entering new parameter names
  in the parameter search widget
* Consider aliases when listing suggested parameters

Changes:

ve.ui.MWParameterSearchWidget.js
* Use hasParameter method instead of using indexOf - uses map lookup
  internally, which is much faster, and also take aliases into account
* Trim query input value to prevent leading or trailing whitespace from
  being considered when filtering known or creating unknown parameters
* Take aliases into account when showing filtered results

ve.dm.MWTransclusionModel.js
* Use original name when round-tripping

ve.dm.MWTemplateParameterModel.js
* Store original name for round tripping, and trim the original name for
  other uses
* Add getOriginalName method

ve.dm.MWTemplateModel.js
* Add hasParameter method, which currently just does a map lookup, but can
  do other processing in the future

ve.dm.MWTemplateSpecModel.js
* Add isParameterKnown method

Bug: 50715
Bug: 50717
Change-Id: I36a5e93ca8938ac3401a6e274647597704700468
2013-07-10 15:34:36 -07:00
jenkins-bot de61c74ff2 Merge "Drop mw:ExtLink/URL support" 2013-07-08 19:13:29 +00:00
Trevor Parscal 37240aca59 Math Node UI
Show an inspector with inputwidget when the user clicks a math
node. The data of the math equation is shown in the
edit box, it can re-render the math tag image when
the inspector is closed, and save the change when
saving the page.

TODO:
* Change the icon from link to math
* Translate title by translatewiki in i18n
* Other further UI improvements

Change-Id: I4d7533af25186cc39cc4bc6a4326d222ffd6db19
2013-07-07 07:32:11 +00:00
jiabao 7eb6efa3b7 Math Node Matcher
This patch creates two files handling math node matching,
which are:
ve.dm.MWMathNode.js - a basic version of toDataElement
and toDomElement functions work
ve.ce.MWMathNode.js - math formulas in VisualEditor are
clickable and render as img tags

Change-Id: Ib909c5fb02e385c88050f42d02d207ab6a97d0dd
2013-07-07 07:32:02 +00:00
Ed Sanders 5df020a5f0 Drop mw:ExtLink/URL support
Because Parsoid has.

Bug: 50734
Change-Id: Id2c893467c5063cc29cd9a91203406b86a3abfbe
2013-07-04 13:18:18 +02:00
Roan Kattouw 92c38eab85 The great directory split of 2013
Move all MW-specific files into the ve-mw directory, in preparation
for moving them out into a separate repo.

All MW-specific files were moved into a parallel directory structure
in modules/ve-mw . Files with both generic and MW-specific things were
split up. Files in ve/init/mw/ were moved to ve-mw/init/ rather than
ve-mw/init/mw ; they're still named ve.init.mw.* but we should change
that. Some of the test files for core classes had MW-specific test cases,
so those were split up and the test runner was duplicated; we should
refactor our tests to use data providers so we can add cases more easily.

Split files:
* ve.ce.Node.css
* ve.ce.ContentBranchNode.test.js (MWEntityNode)
* ve.ce.Document.test.js (some core test cases genericized)
* ve.dm.InternalList.test.js (uses mwReference test document)
* ve.dm.SurfaceFragment.test.js, ve.ui.FormatAction.test.js
** Made core tests use heading instead of mwHeading
** Updated core tests because normal headings don't break out of lists
** Moved test runners into ve.test.utils.js
* ve.ui.Icons-*.css
* ve.ui.Dialog.css (MW parts into ve.ui.MWDialog.css)
* ve.ui.Tool.css
* ve.ui.Widget.css (move ve-ui-rtl and ve-ui-ltr to ve.ui.css)

ve.dm.Converter.test.js: Moved runner functions into ve.test.utils.js

ve.dm.example.js:
* Refactored createExampleDocument so mwExample can use it
* Removed wgExtensionAssetsPath detection, moved into mw-preload.js
* Genericized withMeta example document (original version copied to mwExample)
* Moved references example document to mwExample

ve.dm.mwExample.js:
* Move withMeta and references example documents from ve.dm.example.js
* Add createExampleDocument function

ve-mw/test/index.php: Runner for MW-specific tests only

ve-mw/test/mw-preload.js: Sets VE_TESTDIR for Special:JavaScriptTest only

ve.ui.Window.js:
* Remove magic path interpolation in addLocalStyleSheets()
* Pass full(er) paths to addLocalStyleSheets(), here and in subclasses

ve.ui.MWDialog.js: Subclass of Dialog that adds MW versions of stylesheets

ve.ui.MW*Dialog.js:
* Subclass MWDialog rather than Dialog
* Load both core and MW versions of stylesheets that have both

ve.ui.PagedDialog.js: Converted to a mixin rather than an abstract base class
* Don't inherit ve.ui.Dialog
* Rather than overriding initialize(), provide initializePages() which the
  host class is supposed to call from its initialize()
* Rename onOutlineSelect to onPageOutlineSelect

ve.ui.MWMetaDialog.js, ve.ui.MWTransclusionDialog.js:
* Use PagedDialog as a mixin rather than a base class, inherit MWDialog

bullet-icon.png: Unused, deleted

Stuff we should do later:
* Refactor tests to use data providers
* Write utility function for SVG compat check
* Separate omnibus CSS files such as ve.ui.Widget.css
* Separate omnibus RL modules
* Use icon classes in ViewPageTarget

Change-Id: I1b28f8ba7f2d2513e5c634927a854686fb9dd5a5
2013-07-02 20:51:38 -07:00