ckeditor/plugins/crossreference/plugin.js
author indvd00m (gotoindvdum[at]gmail[dot]com)
Thu, 15 Dec 2016 18:10:20 +0300
changeset 0 44d330dccc59
child 2 467e24fbc60e
permissions -rw-r--r--
Init sample
indvd00m@0
     1
CKEDITOR.plugins.add('crossreference', {
indvd00m@0
     2
	lang : [ 'en', 'ru' ],
indvd00m@0
     3
	requires : 'dialog,notification',
indvd00m@0
     4
	icons : 'crossreference',
indvd00m@0
     5
	hidpi : true,
indvd00m@0
     6
	init : function(editor) {
indvd00m@0
     7
		
indvd00m@0
     8
		// config
indvd00m@0
     9
		
indvd00m@0
    10
		var config = getConfig();
indvd00m@0
    11
		editor.config.crossreference = config;
indvd00m@0
    12
		
indvd00m@0
    13
		// plugin
indvd00m@0
    14
		
indvd00m@0
    15
		var anchorAllowedContent = 'a[!cross-reference,cross-anchor,cross-guid,cross-name,cross-number]{*}(cross-reference,cross-anchor)';
indvd00m@0
    16
		var anchorRequiredContent = 'a[cross-reference,cross-anchor]';
indvd00m@0
    17
		var linkAllowedContent = 'a[!cross-reference,cross-link,cross-guid,cross-name,cross-number]{*}(cross-reference,cross-link)';
indvd00m@0
    18
		var linkRequiredContent = 'a[cross-reference,cross-link]';
indvd00m@0
    19
		editor.addFeature({
indvd00m@0
    20
			name: 'crossreference-anchor',
indvd00m@0
    21
			allowedContent: anchorAllowedContent,
indvd00m@0
    22
			requiredContent: anchorRequiredContent
indvd00m@0
    23
		});
indvd00m@0
    24
		editor.addFeature({
indvd00m@0
    25
			name: 'crossreference-link',
indvd00m@0
    26
			allowedContent: linkAllowedContent,
indvd00m@0
    27
			requiredContent: linkRequiredContent
indvd00m@0
    28
		});
indvd00m@0
    29
		editor.ui.add('crossreference', CKEDITOR.UI_MENUBUTTON, {
indvd00m@0
    30
			label : editor.lang.crossreference.name,
indvd00m@0
    31
			modes: {
indvd00m@0
    32
				wysiwyg: 1,
indvd00m@0
    33
				source: 1 
indvd00m@0
    34
			},
indvd00m@0
    35
			toolbar : 'insert',
indvd00m@0
    36
			onMenu: function() {
indvd00m@0
    37
				var selectedElement = null;
indvd00m@0
    38
				
indvd00m@0
    39
				var selection = editor.getSelection();
indvd00m@0
    40
				if (selection) {
indvd00m@0
    41
					var element = selection.getStartElement();
indvd00m@0
    42
					if (element)
indvd00m@0
    43
						element = element.getAscendant('a', true);
indvd00m@0
    44
					if (element && element.hasAttribute('cross-reference')) {
indvd00m@0
    45
						selectedElement = element;
indvd00m@0
    46
					}
indvd00m@0
    47
				}
indvd00m@0
    48
				
indvd00m@0
    49
				var state = getMenuState(selectedElement, true);
indvd00m@0
    50
				return state;
indvd00m@0
    51
			}
indvd00m@0
    52
		});
indvd00m@0
    53
		
indvd00m@0
    54
		// dialogs
indvd00m@0
    55
		
indvd00m@0
    56
		var updateCmdName = 'update-crossreferences';
indvd00m@0
    57
		var anchorDialogCmdName = 'crossreference-anchor-dialog';
indvd00m@0
    58
		var linkDialogCmdName = 'crossreference-link-dialog';
indvd00m@0
    59
		
indvd00m@0
    60
		CKEDITOR.dialog.add(anchorDialogCmdName, this.path + 'dialogs/crossreference-anchor.js');
indvd00m@0
    61
		CKEDITOR.dialog.add(linkDialogCmdName, this.path + 'dialogs/crossreference-link.js');
indvd00m@0
    62
		
indvd00m@0
    63
		editor.addCommand(anchorDialogCmdName, new CKEDITOR.dialogCommand(anchorDialogCmdName, {
indvd00m@0
    64
			allowedContent: anchorAllowedContent,
indvd00m@0
    65
			requiredContent: anchorRequiredContent
indvd00m@0
    66
		}));
indvd00m@0
    67
		editor.addCommand(linkDialogCmdName, new CKEDITOR.dialogCommand(linkDialogCmdName, {
indvd00m@0
    68
			allowedContent: linkAllowedContent,
indvd00m@0
    69
			requiredContent: linkRequiredContent
indvd00m@0
    70
		}));
indvd00m@0
    71
indvd00m@0
    72
		// commands
indvd00m@0
    73
		
indvd00m@0
    74
		editor.addCommand(updateCmdName, {
indvd00m@0
    75
			async: true,
indvd00m@0
    76
			contextSensitive: false,
indvd00m@0
    77
			editorFocus: false,
indvd00m@0
    78
			modes: {
indvd00m@0
    79
				wysiwyg: 1,
indvd00m@0
    80
				source: 1
indvd00m@0
    81
			},
indvd00m@0
    82
			readOnly: true,
indvd00m@0
    83
			exec: function(editor) {
indvd00m@0
    84
				editor.setReadOnly(true);
indvd00m@0
    85
				var notification = editor.showNotification(editor.lang.crossreference.updatingCrossReferences, 'progress', 0);
indvd00m@0
    86
				
indvd00m@0
    87
				var cmd = this;
indvd00m@0
    88
				
indvd00m@0
    89
				var typesCount = 0;
indvd00m@0
    90
				var processedTypesCount = 0;
indvd00m@0
    91
				for (var typeName in config.types) {
indvd00m@0
    92
					typesCount++;
indvd00m@0
    93
				}
indvd00m@0
    94
				var linksCount = 0;
indvd00m@0
    95
				
indvd00m@0
    96
				var html = null;
indvd00m@0
    97
				if (editor.mode == 'source')
indvd00m@0
    98
					html = $('<div>' + editor.getData() + '</div>');
indvd00m@0
    99
				else
indvd00m@0
   100
					html = $(editor.editable().$);
indvd00m@0
   101
				
indvd00m@0
   102
				function finishCommand() {
indvd00m@0
   103
					editor.setReadOnly(false);
indvd00m@0
   104
					editor.fire('afterCommandExec', {
indvd00m@0
   105
						name: updateCmdName,
indvd00m@0
   106
						command: cmd
indvd00m@0
   107
					});
indvd00m@0
   108
					notification.update({
indvd00m@0
   109
						type: 'success', 
indvd00m@0
   110
						message: editor.lang.crossreference.updatedCrossReferences + linksCount,
indvd00m@0
   111
						important: true
indvd00m@0
   112
					});
indvd00m@0
   113
				}
indvd00m@0
   114
				
indvd00m@0
   115
				if (typesCount == 0) {
indvd00m@0
   116
					finishCommand();
indvd00m@0
   117
					return;
indvd00m@0
   118
				}
indvd00m@0
   119
				
indvd00m@0
   120
				for (var typeName in config.types) {
indvd00m@0
   121
					config.findAnchors(config, editor, config.types[typeName], function(anchors) {
indvd00m@0
   122
						notification.update({
indvd00m@0
   123
							progress: (1 / typesCount) * processedTypesCount 
indvd00m@0
   124
						});
indvd00m@0
   125
						for (var i = 0; i < anchors.length; i++) {
indvd00m@0
   126
							var anchor = anchors[i];
indvd00m@0
   127
							var type = config.types[anchor.type];
indvd00m@0
   128
							
indvd00m@0
   129
							notification.update({
indvd00m@0
   130
								progress: (1 / typesCount) * processedTypesCount + (1 / typesCount / anchors.length) * i
indvd00m@0
   131
							});
indvd00m@0
   132
							
indvd00m@0
   133
							var aName = type.type + '-' + anchor.guid;
indvd00m@0
   134
							
indvd00m@0
   135
							var anchorElement = $('a[cross-reference="' + type.type + '"][cross-anchor][cross-guid="' + anchor.guid + '"]', html);
indvd00m@0
   136
							if (anchorElement.length > 0) {
indvd00m@0
   137
								anchorElement.attr('cross-reference', type.type);
indvd00m@0
   138
								anchorElement.attr('cross-anchor', '');
indvd00m@0
   139
								anchorElement.attr('cross-guid', anchor.guid);
indvd00m@0
   140
								anchorElement.attr('cross-name', anchor.name);
indvd00m@0
   141
								anchorElement.attr('cross-number', anchor.number);
indvd00m@0
   142
								anchorElement.attr('name', aName);
indvd00m@0
   143
								if (!anchorElement.hasClass('cross-reference'))
indvd00m@0
   144
									anchorElement.addClass('cross-reference');
indvd00m@0
   145
								if (!anchorElement.hasClass('cross-anchor'))
indvd00m@0
   146
									anchorElement.addClass('cross-anchor');
indvd00m@0
   147
								
indvd00m@0
   148
								anchorElement.removeAttr('cross-link');
indvd00m@0
   149
								anchorElement.removeClass('cross-link');
indvd00m@0
   150
								
indvd00m@0
   151
								anchorElement.text(anchor.text);
indvd00m@0
   152
							}
indvd00m@0
   153
							
indvd00m@0
   154
							$('a[cross-reference="' + type.type + '"][cross-link][cross-guid="' + anchor.guid + '"]', html).each(function() {
indvd00m@0
   155
								var linkElement = $(this);
indvd00m@0
   156
								
indvd00m@0
   157
								linkElement.attr('cross-reference', type.type);
indvd00m@0
   158
								linkElement.attr('cross-link', '');
indvd00m@0
   159
								linkElement.attr('cross-guid', anchor.guid);
indvd00m@0
   160
								linkElement.attr('cross-name', anchor.name);
indvd00m@0
   161
								linkElement.attr('cross-number', anchor.number);
indvd00m@0
   162
								linkElement.attr('href', '#' + aName);
indvd00m@0
   163
								
indvd00m@0
   164
								if (!linkElement.hasClass('cross-reference'))
indvd00m@0
   165
									linkElement.addClass('cross-reference');
indvd00m@0
   166
								if (!linkElement.hasClass('cross-link'))
indvd00m@0
   167
									linkElement.addClass('cross-link');
indvd00m@0
   168
								
indvd00m@0
   169
								linkElement.removeAttr('cross-anchor');
indvd00m@0
   170
								linkElement.removeClass('cross-anchor');
indvd00m@0
   171
								
indvd00m@0
   172
								var linkText = anchor.text;
indvd00m@0
   173
								if (type.linkTextTemplate)
indvd00m@0
   174
									linkText = config.formatText(type.linkTextTemplate, anchor);
indvd00m@0
   175
								linkElement.text(linkText);
indvd00m@0
   176
								linkElement.attr('title', anchor.text.replace(/&nbsp;/g, ' ').trim());
indvd00m@0
   177
								
indvd00m@0
   178
								linksCount++;
indvd00m@0
   179
							});
indvd00m@0
   180
						}
indvd00m@0
   181
						processedTypesCount++;
indvd00m@0
   182
						if (processedTypesCount >= typesCount) {
indvd00m@0
   183
							// done
indvd00m@0
   184
							if (editor.mode == 'source')
indvd00m@0
   185
								editor.setData(html.html());
indvd00m@0
   186
							finishCommand();
indvd00m@0
   187
						}
indvd00m@0
   188
					});
indvd00m@0
   189
				}
indvd00m@0
   190
			}
indvd00m@0
   191
		});
indvd00m@0
   192
		editor.on('doubleclick', function(evt) {
indvd00m@0
   193
			if (evt.data.element && !evt.data.element.isReadOnly() && evt.data.element.getName() === 'a' 
indvd00m@0
   194
					&& evt.data.element.hasAttribute('cross-reference')) {
indvd00m@0
   195
				editor.getSelection().selectElement(evt.data.element);
indvd00m@0
   196
				if (evt.data.element.hasAttribute('cross-anchor')) {
indvd00m@0
   197
					evt.data.dialog = anchorDialogCmdName;
indvd00m@0
   198
				} else if (evt.data.element.hasAttribute('cross-link')) {
indvd00m@0
   199
					evt.data.dialog = linkDialogCmdName;
indvd00m@0
   200
				}
indvd00m@0
   201
			}
indvd00m@0
   202
		});
indvd00m@0
   203
		
indvd00m@0
   204
		// menu
indvd00m@0
   205
		
indvd00m@0
   206
		var updateMenuItemName = 'updateCrossReferences';
indvd00m@0
   207
		var setAnchorMenuItemName = 'setCrossReferenceAnchor';
indvd00m@0
   208
		var setLinkMenuItemName = 'setCrossReferenceLink';
indvd00m@0
   209
		
indvd00m@0
   210
		var getMenuState = function(element, alwaysAllowEditItems) {
indvd00m@0
   211
			var items = {};
indvd00m@0
   212
			items[updateMenuItemName] = CKEDITOR.TRISTATE_OFF;
indvd00m@0
   213
			if (alwaysAllowEditItems == true) {
indvd00m@0
   214
				items[setAnchorMenuItemName] = CKEDITOR.TRISTATE_OFF;
indvd00m@0
   215
				items[setLinkMenuItemName] = CKEDITOR.TRISTATE_OFF;
indvd00m@0
   216
			}
indvd00m@0
   217
			if (element && element.getName() === 'a' && element.hasAttribute('cross-reference')) {
indvd00m@0
   218
				items[setAnchorMenuItemName] = CKEDITOR.TRISTATE_OFF;
indvd00m@0
   219
				items[setLinkMenuItemName] = CKEDITOR.TRISTATE_OFF;
indvd00m@0
   220
				if (element.hasAttribute('cross-anchor')) {
indvd00m@0
   221
					items[setAnchorMenuItemName] = CKEDITOR.TRISTATE_ON;
indvd00m@0
   222
					items[setLinkMenuItemName] = CKEDITOR.TRISTATE_DISABLED;
indvd00m@0
   223
				}
indvd00m@0
   224
				if (element.hasAttribute('cross-link')) {
indvd00m@0
   225
					items[setAnchorMenuItemName] = CKEDITOR.TRISTATE_DISABLED;
indvd00m@0
   226
					items[setLinkMenuItemName] = CKEDITOR.TRISTATE_ON;
indvd00m@0
   227
				}
indvd00m@0
   228
			}
indvd00m@0
   229
			return items;
indvd00m@0
   230
		}
indvd00m@0
   231
		if (editor.addMenuItem) {
indvd00m@0
   232
			editor.addMenuGroup('crossreferenceGroup');
indvd00m@0
   233
			editor.addMenuItem(updateMenuItemName, {
indvd00m@0
   234
				label : editor.lang.crossreference.updateCrossReferences,
indvd00m@0
   235
				command : updateCmdName,
indvd00m@0
   236
				icon: this.path + 'icons/update.png',
indvd00m@0
   237
				group : 'crossreferenceGroup'
indvd00m@0
   238
			});
indvd00m@0
   239
			editor.addMenuItem(setAnchorMenuItemName, {
indvd00m@0
   240
				label : editor.lang.crossreference.setCrossReferenceAnchor,
indvd00m@0
   241
				command : anchorDialogCmdName,
indvd00m@0
   242
				icon: this.path + 'icons/anchor.png',
indvd00m@0
   243
				group : 'crossreferenceGroup'
indvd00m@0
   244
			});
indvd00m@0
   245
			editor.addMenuItem(setLinkMenuItemName, {
indvd00m@0
   246
				label : editor.lang.crossreference.setCrossReferenceLink,
indvd00m@0
   247
				command : linkDialogCmdName,
indvd00m@0
   248
				icon: this.path + 'icons/link.png',
indvd00m@0
   249
				group : 'crossreferenceGroup'
indvd00m@0
   250
			});
indvd00m@0
   251
		}
indvd00m@0
   252
		if (editor.contextMenu) {
indvd00m@0
   253
			editor.contextMenu.addListener(function(element, selection) {
indvd00m@0
   254
				if (element.getName() === 'a' && element.hasAttribute('cross-reference')) {
indvd00m@0
   255
					selection.selectElement(element);
indvd00m@0
   256
				}
indvd00m@0
   257
				var state = getMenuState(element, false);
indvd00m@0
   258
				return state;
indvd00m@0
   259
			});
indvd00m@0
   260
		}
indvd00m@0
   261
		
indvd00m@0
   262
		function getConfig() {
indvd00m@0
   263
			var defaultConfig = {
indvd00m@0
   264
				activeTypes: ['chapter', 'image', 'table', 'reference'],
indvd00m@0
   265
				overrideTypes: false,
indvd00m@0
   266
				types: {}
indvd00m@0
   267
			};
indvd00m@0
   268
			defaultConfig.types.chapter = {
indvd00m@0
   269
				name: editor.lang.crossreference.chapter,
indvd00m@0
   270
				anchorTextTemplate: '${number}. ${name}.',
indvd00m@0
   271
				linkTextTemplate: '${number}',
indvd00m@0
   272
				numeration: {
indvd00m@0
   273
					enabled: true,
indvd00m@0
   274
					firstNumber: '1',
indvd00m@0
   275
					increase: function(number) {
indvd00m@0
   276
						var n = parseInt(number);
indvd00m@0
   277
						return ++n;
indvd00m@0
   278
					}
indvd00m@0
   279
				},
indvd00m@0
   280
				anchorsProvider: 'default',
indvd00m@0
   281
				allowCreateAnchors: true,
indvd00m@0
   282
				groupAnchors: false
indvd00m@0
   283
			};
indvd00m@0
   284
			defaultConfig.types.image = {
indvd00m@0
   285
				name: editor.lang.crossreference.figure,
indvd00m@0
   286
				anchorTextTemplate: editor.lang.crossreference.fig + ' ${number}. ${name}.',
indvd00m@0
   287
				linkTextTemplate: '${number}',
indvd00m@0
   288
				numeration: {
indvd00m@0
   289
					enabled: true,
indvd00m@0
   290
					firstNumber: '1',
indvd00m@0
   291
					increase: function(number) {
indvd00m@0
   292
						var n = parseInt(number);
indvd00m@0
   293
						return ++n;
indvd00m@0
   294
					}
indvd00m@0
   295
				},
indvd00m@0
   296
				anchorsProvider: 'default',
indvd00m@0
   297
				allowCreateAnchors: true,
indvd00m@0
   298
				groupAnchors: false
indvd00m@0
   299
			};
indvd00m@0
   300
			defaultConfig.types.table = {
indvd00m@0
   301
				name: editor.lang.crossreference.table,
indvd00m@0
   302
				anchorTextTemplate: editor.lang.crossreference.table + ' ${number}. ${name}.',
indvd00m@0
   303
				linkTextTemplate: '${number}',
indvd00m@0
   304
				numeration: {
indvd00m@0
   305
					enabled: true,
indvd00m@0
   306
					firstNumber: '1',
indvd00m@0
   307
					increase: function(number) {
indvd00m@0
   308
						var n = parseInt(number);
indvd00m@0
   309
						return ++n;
indvd00m@0
   310
					}
indvd00m@0
   311
				},
indvd00m@0
   312
				anchorsProvider: 'default',
indvd00m@0
   313
				allowCreateAnchors: true,
indvd00m@0
   314
				groupAnchors: false
indvd00m@0
   315
			};
indvd00m@0
   316
			defaultConfig.types.reference = {
indvd00m@0
   317
				name: editor.lang.crossreference.reference,
indvd00m@0
   318
				anchorTextTemplate: '[${number}] ${name}.',
indvd00m@0
   319
				linkTextTemplate: '[${number}]',
indvd00m@0
   320
				numeration: {
indvd00m@0
   321
					enabled: true,
indvd00m@0
   322
					firstNumber: '1',
indvd00m@0
   323
					increase: function(number) {
indvd00m@0
   324
						var n = parseInt(number);
indvd00m@0
   325
						return ++n;
indvd00m@0
   326
					}
indvd00m@0
   327
				},
indvd00m@0
   328
				anchorsProvider: 'default',
indvd00m@0
   329
				allowCreateAnchors: true,
indvd00m@0
   330
				groupAnchors: false
indvd00m@0
   331
			};
indvd00m@0
   332
			
indvd00m@0
   333
			var config = CKEDITOR.tools.clone(defaultConfig);
indvd00m@0
   334
			if (editor.config.crossreference) {
indvd00m@0
   335
				config = CKEDITOR.tools.extend(config, editor.config.crossreference, true);
indvd00m@0
   336
				if (!config.overrideTypes) {
indvd00m@0
   337
					for (var typeName in defaultConfig.types) {
indvd00m@0
   338
						var type = defaultConfig.types[typeName];
indvd00m@0
   339
						if (!(typeName in config.types))
indvd00m@0
   340
							config.types[typeName] = type;
indvd00m@0
   341
					}
indvd00m@0
   342
				}
indvd00m@0
   343
			}
indvd00m@0
   344
			for (var typeName in config.types) {
indvd00m@0
   345
				var type = config.types[typeName];
indvd00m@0
   346
				type.type = typeName;
indvd00m@0
   347
			}
indvd00m@0
   348
			for (var typeName in config.types) {
indvd00m@0
   349
				if ($.inArray(typeName, config.activeTypes) == -1) {
indvd00m@0
   350
					delete config.types[typeName];
indvd00m@0
   351
				}
indvd00m@0
   352
			}
indvd00m@0
   353
			
indvd00m@0
   354
			// shared methods
indvd00m@0
   355
			
indvd00m@0
   356
			config.findAnchors = function(config, editor, type, callback) {
indvd00m@0
   357
				var anchors = [];
indvd00m@0
   358
				
indvd00m@0
   359
				if (type == null) {
indvd00m@0
   360
					callback(anchors);
indvd00m@0
   361
					return;
indvd00m@0
   362
				}
indvd00m@0
   363
				
indvd00m@0
   364
				var number = null;
indvd00m@0
   365
				if (type.numeration && type.numeration.enabled)
indvd00m@0
   366
					number = type.numeration.firstNumber + '';
indvd00m@0
   367
				
indvd00m@0
   368
				var html = null;
indvd00m@0
   369
				if (editor.mode == 'source')
indvd00m@0
   370
					html = $('<div>' + editor.getData() + '</div>');
indvd00m@0
   371
				else
indvd00m@0
   372
					html = $(editor.editable().$);
indvd00m@0
   373
				
indvd00m@0
   374
				$('a[cross-reference="' + type.type + '"][cross-anchor]', html).each(function() {
indvd00m@0
   375
					var element = $(this);
indvd00m@0
   376
					var anchor = {
indvd00m@0
   377
						type: element.attr('cross-reference'),
indvd00m@0
   378
						guid: element.attr('cross-guid'),
indvd00m@0
   379
						name: element.attr('cross-name'),
indvd00m@0
   380
						number: number,
indvd00m@0
   381
						text: element.text()
indvd00m@0
   382
					}
indvd00m@0
   383
					anchors.push(anchor);
indvd00m@0
   384
					if (type.numeration && type.numeration.enabled)
indvd00m@0
   385
						number = type.numeration.increase(number);
indvd00m@0
   386
				});
indvd00m@0
   387
				
indvd00m@0
   388
				function postProcessAnchors(anchors) {
indvd00m@0
   389
					for(var i = 0; i < anchors.length; i++) {
indvd00m@0
   390
						var anchor = anchors[i];
indvd00m@0
   391
						
indvd00m@0
   392
						if (anchor.type != type.type)
indvd00m@0
   393
							throw 'Incompatible type: ' + type.type;
indvd00m@0
   394
						
indvd00m@0
   395
						var text = anchor.name;
indvd00m@0
   396
						if (type.anchorTextTemplate) {
indvd00m@0
   397
							text = config.formatText(type.anchorTextTemplate, anchor);
indvd00m@0
   398
						}
indvd00m@0
   399
						anchor.text = text;
indvd00m@0
   400
					}
indvd00m@0
   401
					callback(anchors);
indvd00m@0
   402
				}
indvd00m@0
   403
				
indvd00m@0
   404
				if (type.anchorsProvider && type.anchorsProvider !== 'default') {
indvd00m@0
   405
					type.anchorsProvider(postProcessAnchors, anchors, type, editor);
indvd00m@0
   406
				} else {
indvd00m@0
   407
					postProcessAnchors(anchors);
indvd00m@0
   408
				}
indvd00m@0
   409
			};
indvd00m@0
   410
			
indvd00m@0
   411
			config.formatText = function(template, anchor) {
indvd00m@0
   412
				var text = template;
indvd00m@0
   413
				
indvd00m@0
   414
				for (var propName in anchor) {
indvd00m@0
   415
					var propValue = anchor[propName];
indvd00m@0
   416
					var regexp = new RegExp('\\$\\{' + propName + '\\}', 'g');
indvd00m@0
   417
					if (propValue)
indvd00m@0
   418
						text = text.replace(regexp, propValue);
indvd00m@0
   419
					else
indvd00m@0
   420
						text = text.replace(regexp, '');
indvd00m@0
   421
				}
indvd00m@0
   422
				
indvd00m@0
   423
				if (anchor.level != null) {
indvd00m@0
   424
					var shift = '';
indvd00m@0
   425
					for (var i = 0; i < anchor.level; i++)
indvd00m@0
   426
						shift += '&nbsp;&nbsp;';
indvd00m@0
   427
					
indvd00m@0
   428
					text = text.replace(/\$\{levelShift\}/g, shift);
indvd00m@0
   429
				}
indvd00m@0
   430
				
indvd00m@0
   431
				text = text.trim();
indvd00m@0
   432
				
indvd00m@0
   433
				return text;
indvd00m@0
   434
			}
indvd00m@0
   435
			
indvd00m@0
   436
			return config;
indvd00m@0
   437
		}
indvd00m@0
   438
	}
indvd00m@0
   439
});