Completed
Push — develop ( 48b424...bab30d )
by Daniel
15:53 queued 09:41
created

tinymce.PluginManager.add(ꞌautolinkꞌ)   F

Complexity

Conditions 29
Paths 1348

Size

Total Lines 141

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 141
rs 2
c 0
b 0
f 0
cc 29
nc 1348
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like tinymce.PluginManager.add(ꞌautolinkꞌ) often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/**
2
 * plugin.js
3
 *
4
 * Released under LGPL License.
5
 * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
6
 *
7
 * License: http://www.tinymce.com/license
8
 * Contributing: http://www.tinymce.com/contributing
9
 */
10
11
/*global tinymce:true */
12
13
tinymce.PluginManager.add('autolink', function(editor) {
0 ignored issues
show
Bug introduced by
The variable tinymce seems to be never declared. If this is a global, consider adding a /** global: tinymce */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
14
	var AutoUrlDetectState;
15
	var AutoLinkPattern = /^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+\-]+@)(.+)$/i;
16
17
	if (editor.settings.autolink_pattern) {
18
		AutoLinkPattern = editor.settings.autolink_pattern;
19
	}
20
21
	editor.on("keydown", function(e) {
22
		if (e.keyCode == 13) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if e.keyCode == 13 is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
23
			return handleEnter(editor);
24
		}
25
	});
26
27
	// Internet Explorer has built-in automatic linking for most cases
28
	if (tinymce.Env.ie) {
0 ignored issues
show
Bug introduced by
The variable tinymce seems to be never declared. If this is a global, consider adding a /** global: tinymce */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
29
		editor.on("focus", function() {
30
			if (!AutoUrlDetectState) {
31
				AutoUrlDetectState = true;
32
33
				try {
34
					editor.execCommand('AutoUrlDetect', false, true);
35
				} catch (ex) {
36
					// Ignore
37
				}
38
			}
39
		});
40
41
		return;
42
	}
43
44
	editor.on("keypress", function(e) {
45
		if (e.keyCode == 41) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if e.keyCode == 41 is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
46
			return handleEclipse(editor);
47
		}
48
	});
49
50
	editor.on("keyup", function(e) {
51
		if (e.keyCode == 32) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if e.keyCode == 32 is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
52
			return handleSpacebar(editor);
53
		}
54
	});
55
56
	function handleEclipse(editor) {
57
		parseCurrentLine(editor, -1, '(', true);
0 ignored issues
show
Bug introduced by
The call to parseCurrentLine seems to have too many arguments starting with true.
Loading history...
58
	}
59
60
	function handleSpacebar(editor) {
61
		parseCurrentLine(editor, 0, '', true);
0 ignored issues
show
Bug introduced by
The call to parseCurrentLine seems to have too many arguments starting with true.
Loading history...
62
	}
63
64
	function handleEnter(editor) {
65
		parseCurrentLine(editor, -1, '', false);
0 ignored issues
show
Bug introduced by
The call to parseCurrentLine seems to have too many arguments starting with false.
Loading history...
66
	}
67
68
	function parseCurrentLine(editor, end_offset, delimiter) {
69
		var rng, end, start, endContainer, bookmark, text, matches, prev, len, rngText;
70
71
		function scopeIndex(container, index) {
72
			if (index < 0) {
73
				index = 0;
74
			}
75
76
			if (container.nodeType == 3) {
77
				var len = container.data.length;
78
79
				if (index > len) {
80
					index = len;
81
				}
82
			}
83
84
			return index;
85
		}
86
87
		function setStart(container, offset) {
88
			if (container.nodeType != 1 || container.hasChildNodes()) {
89
				rng.setStart(container, scopeIndex(container, offset));
90
			} else {
91
				rng.setStartBefore(container);
92
			}
93
		}
94
95
		function setEnd(container, offset) {
96
			if (container.nodeType != 1 || container.hasChildNodes()) {
97
				rng.setEnd(container, scopeIndex(container, offset));
98
			} else {
99
				rng.setEndAfter(container);
100
			}
101
		}
102
103
		// Never create a link when we are inside a link
104
		if (editor.selection.getNode().tagName == 'A') {
105
			return;
106
		}
107
108
		// We need at least five characters to form a URL,
109
		// hence, at minimum, five characters from the beginning of the line.
110
		rng = editor.selection.getRng(true).cloneRange();
111
		if (rng.startOffset < 5) {
112
			// During testing, the caret is placed between two text nodes.
113
			// The previous text node contains the URL.
114
			prev = rng.endContainer.previousSibling;
115
			if (!prev) {
116
				if (!rng.endContainer.firstChild || !rng.endContainer.firstChild.nextSibling) {
117
					return;
118
				}
119
120
				prev = rng.endContainer.firstChild.nextSibling;
121
			}
122
123
			len = prev.length;
124
			setStart(prev, len);
125
			setEnd(prev, len);
126
127
			if (rng.endOffset < 5) {
128
				return;
129
			}
130
131
			end = rng.endOffset;
132
			endContainer = prev;
133
		} else {
134
			endContainer = rng.endContainer;
135
136
			// Get a text node
137
			if (endContainer.nodeType != 3 && endContainer.firstChild) {
138
				while (endContainer.nodeType != 3 && endContainer.firstChild) {
139
					endContainer = endContainer.firstChild;
140
				}
141
142
				// Move range to text node
143
				if (endContainer.nodeType == 3) {
144
					setStart(endContainer, 0);
145
					setEnd(endContainer, endContainer.nodeValue.length);
146
				}
147
			}
148
149
			if (rng.endOffset == 1) {
150
				end = 2;
151
			} else {
152
				end = rng.endOffset - 1 - end_offset;
153
			}
154
		}
155
156
		start = end;
157
158
		do {
159
			// Move the selection one character backwards.
160
			setStart(endContainer, end >= 2 ? end - 2 : 0);
161
			setEnd(endContainer, end >= 1 ? end - 1 : 0);
162
			end -= 1;
163
			rngText = rng.toString();
164
165
			// Loop until one of the following is found: a blank space, &nbsp;, delimiter, (end-2) >= 0
166
		} while (rngText != ' ' && rngText !== '' && rngText.charCodeAt(0) != 160 && (end - 2) >= 0 && rngText != delimiter);
167
168
		if (rng.toString() == delimiter || rng.toString().charCodeAt(0) == 160) {
169
			setStart(endContainer, end);
170
			setEnd(endContainer, start);
171
			end += 1;
0 ignored issues
show
Unused Code introduced by
The assignment to variable end seems to be never used. Consider removing it.
Loading history...
172
		} else if (rng.startOffset === 0) {
173
			setStart(endContainer, 0);
174
			setEnd(endContainer, start);
175
		} else {
176
			setStart(endContainer, end);
177
			setEnd(endContainer, start);
178
		}
179
180
		// Exclude last . from word like "www.site.com."
181
		text = rng.toString();
182
		if (text.charAt(text.length - 1) == '.') {
183
			setEnd(endContainer, start - 1);
184
		}
185
186
		text = rng.toString();
187
		matches = text.match(AutoLinkPattern);
188
189
		if (matches) {
190
			if (matches[1] == 'www.') {
191
				matches[1] = 'http://www.';
192
			} else if (/@$/.test(matches[1]) && !/^mailto:/.test(matches[1])) {
193
				matches[1] = 'mailto:' + matches[1];
194
			}
195
196
			bookmark = editor.selection.getBookmark();
197
198
			editor.selection.setRng(rng);
199
			editor.execCommand('createlink', false, matches[1] + matches[2]);
200
201
			if (editor.settings.default_link_target) {
202
				editor.dom.setAttrib(editor.selection.getNode(), 'target', editor.settings.default_link_target);
203
			}
204
205
			editor.selection.moveToBookmark(bookmark);
206
			editor.nodeChanged();
207
		}
208
	}
209
});
210