The HTML "1<br/>2" was being converted to a linmod that looked like
"<p>1</p><br></br><p>2</p>". This commit fixes the wrapping logic such
that the result is "<p>1<br></br>2</p>" instead. In general, inline
nodes (content nodes) should not interrupt the wrapping, but block nodes
should.
This creates a problem for alien nodes: normally, we determine whether an
alien node is a block alien or an inline alien based on context, but if
we're in wrapping mode we're unsure of the context. We can't tell the
difference between "1<tt>Foo</tt>2" (should be wrapped as one, because
tt is inline) and "1<figure></figure>2" (1 and 2 should be wrapped
separately, because figure is block) using context alone, so in these
cases (and ONLY in these cases) we look up whether the HTML tag in
question is an inline tag or a block tag and use that to decide.
Change-Id: I75e7f3da387dd401d9b93e09a21751951eccbb83
* Added comments to classes and methods
* Quieted a jshint warning
* Broke some long lines
* Replaced instances of "var\t" with "var "
Change-Id: I1d617ed9e5180f1a3dff42078fb5debb5d718407
Firefox triggers a keypress event for backspace. We handle backspace in keydown, so this keypress event should be ignored.
Change-Id: I6a481dbd5df0cf4558a5f1975717ca809250ccda
* CenterNode missing in ResourceLoader registry
* UI classes and rangy not in static test/index.html
* Transaction and TransactionProcessor listed twice
Added a maintenance script that generates the <script> and <link> tags for all
files in the same order everywhere.
Change-Id: I5d22d33769b4e356e8065d295505f6f9a8b0bea8
If you select some text and start typing, we will now remove the content in the range and new content will be annotated with the annotations from the first character in the deleted range. This is similar to other editors.
Change-Id: I46ced52665ab10f9b724dbb225df5687c18a4c3a
Exception was caused by passing -1 to getAnnotationsFromOffset(). So
check for -1 before passing it in; getNearestContentOffset() can
legitimately return -1 if there are no content offsets in the document,
which occurs when the document is empty.
I was originally going to change getNearestContentOffset(start - 1, -1)
to getRelativeContentOffset(start, -1), but Inez correctly pointed out
that that would have unwanted results when near an inline node.
Change-Id: Ife4b497b1c5fd04d411bb25cea99e6ea2abf146f
This was reproducible by blanking the entire document (Ctrl+A Delete),
then undoing that (Ctrl+Z). AFAIK that's the only way to trigger an
insertion on a document that is completely empty.
Change-Id: I22252d5972a413dff614880a90c4c6b22e79672d
Also changed from using "type" to "name" to make it less specific and added a test to make sure it's working.
Change-Id: I150a7ab1a57b3df85b459dbc411c2eaefe08b5bb
The annotation-related code in the converter is greatly simplified
because the API itself takes care of almost everything already.
Change-Id: Ib48f52bad6b650a05dc4e7ef82db4158c19b3cf5
This changes ve.dm.LinkAnnotation to be a generic annotation for <a>
tags, and adds ve.dm.MWInternalLinkAnnotation and
ve.dm.MWExternalLinkAnnotation as MW-specific subclasses. This nicely
splits out the MW-specific parts in LinkAnnotation, and ideally we'd
also move these files somewhere else to reflect their MW-specificity,
but I haven't gotten to that yet.
Similarly, ve.dm.TextStyleAnnotation is now a generic base class for
simple tag-only-no-metadata annotations, and it has 11 subclasses, one
for each tag we support. This is quite a bit more verbose than the
previous code, but I think it's cleaner and more flexible. I considered
writing a function that would generate a TextStyleAnnotation subclass,
then calling that 11 times, but that's not possible if we want to keep
named functions for the constructors.
Change-Id: Ifba10153eef40280e44025dd72d4e9d9f33b0632
Fleshes out ve.dm.Annotation to a class. Annotations in the linear model
will be instances of a subclass of ve.dm.Annotation. Annotations are
defined by subclassing ve.dm.Annotation and registering this subclass
with ve.dm.AnnotationFactory.
ve.dm.AnnotationFactory keeps track of which annotation classes are known,
and has code to match an HTML element to an annotation class, for use in
the converter.
Change-Id: I68802bdb8736ced1f9e04ee49c623944b448141c
The cursor will move natively when it can, allowing for word jumping with alt/ctrl keys. Special conditions exist for slugs and node boundaries that result in programatic movement.
Change-Id: Ife156bf94d8192ddd322c016ca8359855b17d7fc
Removing check for insertAnnotations length because it's also important to know if we're pre-unannotating text.
Change-Id: I7fab39ca353d7656de3ce2985a821cb54384100e
Utility function to generate an opening HTML tag. Needed to integrate
the new annotation API with ve.ce.TextNode
Change-Id: I6804bbf6f79346fde1887fa82d29ec5cd0342d60
Previously, Undo used a transaction's lengthDifference to calculate the selection to display after the transaction was undone. Now, translateOffset with the reversed boolean set to true will properly translate the inverse of a transaction's selection change. Fixes bug #40538
Change-Id: I110bc0cbb5824547842efd391b9f2948b037b758
We were populating empty content nodes with zero-length text nodes to
make round-trip tests in the test suite work (otherwise blanking a
paragraph leaves behind a zero-length text node whereas creating an
empty paragraph does not), but the empty nodes are causing problems in
CE apparently.
* Do not create empty text nodes when constructing a node tree
* Be more careful with text-only replacements:
** Don't resize a text node to zero, remove it instead
** There may not be a text node to resize at all, build it in that case
** Switch nodeRange to nodeOuterRange, this was probably broken before
Tests:
* Change test case for zero-length text node to assert that there is
*no* zero-length text node :)
* Remove a test case concerning an empty text node from the
ve.ce.TextNode suite
Change-Id: Ie677457f2f0a7823a517ba3077b844ef52a20fcc
Previously tests for inheritClass (and other object management
utilities) were absent (as they were copied from upstream K-js).
I've copied the upstream test suite for this method here and
extended it with tests for this new feature.
Had to add es5:true to .jshintrc due to a bug in JSHint.
Repeated the setting in ve.inheritClass for future reference.
Source: https://github.com/Krinkle/K-js/blob/master/test/K.test.js
Change-Id: I63ac620d6ce7832ebfee454ddf7b7c90f6eb6121
This works just fine, as also previously tested/proven by
ve.cloneObject, which uses the same concept of creating an object
identical to what invoking the constructor with "new" would do,
but without invoking the constructor function (which has side-
effects).
Except in this case we do invoke the constructor function, but
we can't use new in ve.Factory because of the arbitrary number of
arguments.
Added a test to assert that 3+ arguments and that instanceof
work as expected.
Change-Id: If0add3da7475886e476900044acda2ba7d01fb11
Add some missing constructor names and rename the ones with a
lowercase 'v'.
I previously changed Object.create and others to using hasOwn,
but that turned out to be useless. The thought at the time was
to only use the native one if it really is a native one (and not
a polyfill from another script), however in then hasOwn is only
relevant on prototypes and when negated. For static members it
would be an own-property either way.
Follows-up:
* Id6783fcfc35a896db088ff424ff9faaabcaff716 (metanode)
* Iab763954fb8cf375900d7a9a92dec1c755d5407e (object-management)
Change-Id: Ia6ef597e5e5453277472dfc23f25d2878b68b7f6
I think what happened here is I added the skeleton code, Kranitor came through and removed the unused arguments, then I merged in my implementations without pulling, then pushed - git merged cleanly, the arguments I thought were there were not there, and tests broke.
Change-Id: I5aa2968fef164c774a10db83a6df1753c93cd2dc
Specifically, go to [[mw:VisualEditor/Feedback]] rather than [[mw:Visual editor/
Feedback]], as the primary set of pages on MWwiki have been moved some time ago
and right now we're stranding users' feedback messages at the wrong place.
Change-Id: Ia2ba0dad7d1bf0d1633fe2704a2e8354285c66da
This allowed me to move ve.ce.Surface particulars (such as the starting, stopping and clearing of polling) out of the UI code.
Also cleaned up some switch statements.
Change-Id: I7b85e42a4e01f8d76237d995e25275f2424541ea
Previously, we were looking one offset to the left to load the insertAnnotations. This would fail at the beginning of a document that began with a slug, and probably other cases too. Now using getRelativeContent offset.
Change-Id: I31b24e2ccfa9fda2ce7fb19d1221f8708a96083f
Slugs aren't represented in the model at all, but in the DOM they do
contain a single character ( or ), so we have to override
the return value of getDomText() to be empty.
Change-Id: Ic93cb694b0632bc81d8d0749149e4d739232ed48
Iterating forwards while removing from an array is a good way to get half way there and be confused as hell.
Change-Id: I74db84eee87c73d8e035f6dc8a92be0d0b9b3dad
* Added some new icons (to be used soon in the inspector redesign)
* Added right-to-left icons for lists
* Renamed some icons for future RTL use
Change-Id: I10e3e3fcda82786e3064176e7eefe211b88db95c
Was cloning the original set, then adding to it - resulting in always containing the whole set in any match.
Also using test instead of exec since exec returns a string result, which under strange circumstances could return a falsy result, despite the RegExp finding a match.
Change-Id: I09a7cb264521d58f02d6ff2547edad9a740b23b2
Surface model annotate method previously cleared basic tool annotation objects.
Now that bold and other annotations have htmlAttributes from parsoid,
we must gather annotations by type from selection and iterate through
to properly clear.
Change-Id: Id53bf5733078524ae5aac376e01b9679eb8c32df
Rather than each tool requesting annotations, and nodes pertaining to selection,
Emitted event supplies annotations and nodes to each tool's update method.
Using select vs. of traverseLeafNodes for code optimization.
Better documentation for updateTools()
Removed unneeded code.
Change-Id: I7c0baa1cc0f7fb731d6e28b175a76e931e9e2961
* Added documentation for ve.AnnotationSet
* Replaced uses of "// Inheritance" with "// parent Constructor"
* Added "// Mixin constructor" where needed
* Added missing section comments like "/* Static Methods */"
* Cleaned up excessive newlines (matching /\n\n\n/g)
* Put unnecessarily multi-line statements on a single line
Change-Id: I2c9b47ba296f7dd3c9cc2985581fbcefd6d76325
* Commands for Sublime:
Find*: "(\* @[a-z]+) ([^{].*) \{(.*)\}"
Replace: "$1 {$3} $2"
Save all && Close all
Find: " function("
Replace: " function ("
Save all && Close all
Find: "Intialization"
Replace: "Initialization"
Save all && Close all
* Consistent use of types (documented in CODING.rm):
- Merged {Integer} into {Number}.
- Merged {DOM Node} into {DOMElement}.
* Remove work-around /*jshint newcap: false */ from ve.js
Calling Object() as a function to to use the internal
toObject no longer throws a newcap warning in JSHint.
It only does that normal functions now .
(e.g. var a = Cap(); or var a = new uncap();)
* Add missing annotations (@static, @method, ..).
* Remove unused variables
* Remove null-assignments to variables that should just be
undefined. There's a few variables explicitly set to null
whereas they are set a few lines under and not used otherwise
(e.g. 'tx' in ve.ce.Surface.prototype.onPaste)
Change-Id: I0721a08f8ecd93c25595aedaa1aadb0e08b83799
Detecting page status in a similar way as WikiEditor inspector.
Disabled accept button now behaves appropriately.
Accept button status is now evaluated on enter or submit.
Change-Id: Ibfef6ffd87cb9a71e37242d6214d0f8e3af2e2c0
This node type represents <meta> or <link> (transparently, based on the
style attribute). I had to make two node types for this and hack the
toData conversion code directly into ve.dm.Converter, because we don't
have native support for node types that can be both inline and block.
(We should add this in the node API rewrite.)
The CE implementation renders a placeholder (with the same styles as an
alien node) right now. I'm not sure how nice that is, but it's better
than rendering raw <meta>/<link> tags.
This whole thing is a total pile of hacks to make VE deal with
<meta>/<link> tags until we have a proper node types API.
Change-Id: Id6783fcfc35a896db088ff424ff9faaabcaff716
Icon appears when scrolling and resizing window.
Instead of always setting the context on scroll and resize, bind to the
updateContextIcon method.
Icon appears when selecting a non content data offset.
Changed logic to show icon changed to content length vs range difference.
Move Link inspector getSelectionText to ve.dm.document getText.
Rationale, more bits of the code depend on evaluating content.
Added new ve.Range truncate method.
Remove getSelectionText, using truncate range & document.getText instead.
Change-Id: Ibd3e99c923f18d2c96a86d92e74e2e9ebd49c85f
This was broken in three different ways:
* On the way in, we were applying whitespace to an array of elements
rather than the actual element, so the whitespace wasn't stored.
* Whitespace processing on the way out was skipped for aliens because
they had their own code path. Refactored this so alien openings and
regular openings share much more code, including whitespace output.
* Somewhat unrelatedly, innerPost output was broken for paragraphs
containing inline elements, because the inline elements' processing
polluted lastOuterPost. Discovered this because my test with inline
aliens also happened to be the first test of whitespace preservation
in paragraphs with inline content elements. Fixed by explicitly
skipping content nodes when outputting whitespace.
Fixed these issues and added a test case.
Change-Id: I8edb61a008e60ace886b1a841b3417682ec39c32
* For the most common case:
- replace ve.extendClass with ve.inheritClass (chose slightly
different names to detect usage of the old/new one, and I
like 'inherit' better).
- move it up to below the constructor, see doc block for why.
* Cases where more than 2 arguments were passed to
ve.extendClass are handled differently depending on the case.
In case of a longer inheritance tree, the other arguments
could be omitted (like in "ve.ce.FooBar, ve.FooBar,
ve.Bar". ve.ce.FooBar only needs to inherit from ve.FooBar,
because ve.ce.FooBar inherits from ve.Bar).
In the case of where it previously had two mixins with
ve.extendClass(), either one becomes inheritClass and one
a mixin, both to mixinClass().
No visible changes should come from this commit as the
instances still all have the same visible properties in the
end. No more or less than before.
* Misc.:
- Be consistent in calling parent constructors in the
same order as the inheritance.
- Add missing @extends and @param documentation.
- Replace invalid {Integer} type hint with {Number}.
- Consistent doc comments order:
@class, @abstract, @constructor, @extends, @params.
- Fix indentation errors
A fairly common mistake was a superfluous space before the
identifier on the assignment line directly below the
documentation comment.
$ ack "^ [^*]" --js modules/ve
- Typo "Inhertiance" -> "Inheritance".
- Replacing the other confusing comment "Inheritance" (inside
the constructor) with "Parent constructor".
- Add missing @abstract for ve.ui.Tool.
- Corrected ve.FormatDropdownTool to ve.ui.FormatDropdownTool.js
- Add function names to all @constructor functions. Now that we
have inheritance it is important and useful to have these
functions not be anonymous.
Example of debug shot: http://cl.ly/image/1j3c160w3D45
Makes the difference between
< documentNode;
> ve_dm_DocumentNode
...
: ve_dm_BranchNode
...
: ve_dm_Node
...
: ve_dm_Node
...
: Object
...
without names (current situation):
< documentNode;
> Object
...
: Object
...
: Object
...
: Object
...
: Object
...
though before this commit, it really looks like this
(flattened since ve.extendClass really did a mixin):
< documentNode;
> Object
...
...
...
Pattern in Sublime (case-sensitive) to find nameless
constructor functions:
"^ve\..*\.([A-Z])([^\.]+) = function \("
Change-Id: Iab763954fb8cf375900d7a9a92dec1c755d5407e
In preparation of pushing the object-management branch, which
will need more shared variables (for efficiency) creating
a shared closure. To avoid a spegetti of immediately-invoked
functions that return functions (like ve.getObjectValues and
ve.getObjectKeys).
Less duplication of code and faster execution.
First I had the closure around it as-is but then I figured it'd
be faster to have a local reference to ve (instead of having to
go through implied globals for references to other ve.*)
So I made it a local variable and then exposed it. That way
anything inside referring to each other stays within the same
scope.
Review with ignore-whitespace for clarity.
Change-Id: I415d8635db6d82cf239f0364ccc2d63a61bd5a6d
Introduced the ve.AnnotationSet class to manage sets of annotations. This
is a generalization of ve.OrderedHashSet, a class that manages a set
using an array and an object keyed by hash.
Converted everything that stores, tracks or passes around annotations to
use ve.AnnotationSet. In particular, this means the linear model now
contains AnnotationSets instead of hash-keyed objects.
This allows us to maintain the order of annotations in the linear model,
and will help fix bugs with annotation ordering and splitting.
Change-Id: I50975b0a95f4cc33017a0b59fdede9ed1eff0124
Currently this is done in a hacky way because we don't have a real
registry of RDFa types for node types, so we just hardcode the list of
recognized types (only links currently).
Change-Id: I5afcc55701fc6fa0ee2a360dcf5ca62b065292f5
* Also clean up ve.init.mw.ViewPageTarget...setupSaveDialog
Consistently use viewPage instead of 'this' inside this
function. The reason it is locally aliased is because there is
other 'this'es used here. Using them mixed is even more
confusing.
- No need for ve.bind, other handlers in this function also
just use viewPage instead of binding this.
Change-Id: I25e93862a39134961bf80835f46cbf531d8109e0