better syntax highlighter demo, some bugfixes
This commit is contained in:
parent
37219bfbe9
commit
0b629a1b40
4 changed files with 214 additions and 189 deletions
|
@ -3,48 +3,61 @@ Ox.load('UI', {
|
||||||
theme: 'classic'
|
theme: 'classic'
|
||||||
}, function() {
|
}, function() {
|
||||||
|
|
||||||
Ox.Theme('classic');
|
var $button = Ox.Button({
|
||||||
|
title: 'Run',
|
||||||
var $body = $('body'),
|
width: 256
|
||||||
$textarea = new Ox.Input({
|
})
|
||||||
height: 400,
|
.css({
|
||||||
|
marginTop: '256px'
|
||||||
|
})
|
||||||
|
.click(function() {
|
||||||
|
$syntaxHighlighter.options({
|
||||||
|
source: $textarea.value()
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
$options = Ox.Element()
|
||||||
|
.append(
|
||||||
|
Ox.FormElementGroup({
|
||||||
|
elements: ['showLineNumbers', 'showLinebreaks', 'showTabs', 'showWhitespace'].map(function(v, i) {
|
||||||
|
return Ox.Checkbox({
|
||||||
|
overlap: 'right',
|
||||||
|
title: Ox.toDashes(v).split('-').map(function(v) { return Ox.toTitleCase(v); }).join(' '),
|
||||||
|
width: 160
|
||||||
|
}).bindEvent({
|
||||||
|
change: function(event) {
|
||||||
|
$syntaxHighlighter.options(v, event.checked);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
),
|
||||||
|
$syntaxHighlighter = Ox.SyntaxHighlighter(),
|
||||||
|
$textarea = Ox.Input({
|
||||||
|
height: 256,
|
||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
width: 400
|
width: 256
|
||||||
})
|
})
|
||||||
.css({
|
.css({
|
||||||
fontFamily: 'Menlo, Monaco, Courier, Courier New'
|
fontFamily: 'Menlo, Monaco, Courier, Courier New'
|
||||||
})
|
});
|
||||||
.appendTo($body),
|
|
||||||
$button = new Ox.Button({
|
Ox.SplitPanel({
|
||||||
title: 'Run',
|
elements: [
|
||||||
width: 40
|
{
|
||||||
})
|
element: Ox.Element()
|
||||||
.css({
|
.append($textarea)
|
||||||
position: 'absolute',
|
.append($button),
|
||||||
left: '8px',
|
resizable: true,
|
||||||
top: '416px',
|
resize: [128, 256, 384],
|
||||||
})
|
size: 256
|
||||||
.bindEvent({
|
},
|
||||||
click: function() {
|
{
|
||||||
$div.empty();
|
element: Ox.Container()
|
||||||
new Ox.SyntaxHighlighter({
|
.append($options)
|
||||||
showLinebreaks: true,
|
.append($syntaxHighlighter)
|
||||||
showTabs: true,
|
|
||||||
showWhitespace: true,
|
|
||||||
source: $textarea.value(),
|
|
||||||
//stripComments: true,
|
|
||||||
//stripLinebreaks: true,
|
|
||||||
//stripWhitespace: true,
|
|
||||||
}).appendTo($div);
|
|
||||||
}
|
}
|
||||||
})
|
],
|
||||||
.appendTo($body),
|
orientation: 'horizontal'
|
||||||
$div = $('<div>')
|
}).appendTo(Ox.UI.$body)
|
||||||
.css({
|
|
||||||
position: 'absolute',
|
|
||||||
left: '416px',
|
|
||||||
top: '8px'
|
|
||||||
})
|
|
||||||
.appendTo($body);
|
|
||||||
|
|
||||||
});
|
});
|
|
@ -129,6 +129,7 @@ Ox.DocPage = function(options, self) {
|
||||||
);
|
);
|
||||||
$elements.push(
|
$elements.push(
|
||||||
Ox.SyntaxHighlighter({
|
Ox.SyntaxHighlighter({
|
||||||
|
showLineNumbers: true,
|
||||||
// fixme: silly
|
// fixme: silly
|
||||||
source: item.source.map(function(token) {
|
source: item.source.map(function(token) {
|
||||||
return token.source;
|
return token.source;
|
||||||
|
|
|
@ -7,11 +7,12 @@
|
||||||
Ox.SyntaxHighlighter = function(options, self) {
|
Ox.SyntaxHighlighter = function(options, self) {
|
||||||
|
|
||||||
self = self || {};
|
self = self || {};
|
||||||
var that = new Ox.Element({}, self)
|
var that = Ox.Element({}, self)
|
||||||
.defaults({
|
.defaults({
|
||||||
height: 40,
|
height: 40,
|
||||||
lineLength: 80, //@ number of characters per line
|
lineLength: 80, //@ number of characters per line
|
||||||
offset: 1, //@ first line number
|
offset: 1, //@ first line number
|
||||||
|
showLineNumbers: false,
|
||||||
showLinebreaks: false, //@ show linebreak symbols
|
showLinebreaks: false, //@ show linebreak symbols
|
||||||
showTabs: false, //@ show tab symbols
|
showTabs: false, //@ show tab symbols
|
||||||
showWhitespace: false, //@ show irregular leading or trailing whitespace
|
showWhitespace: false, //@ show irregular leading or trailing whitespace
|
||||||
|
@ -25,10 +26,31 @@ Ox.SyntaxHighlighter = function(options, self) {
|
||||||
.options(options || {})
|
.options(options || {})
|
||||||
.addClass('OxSyntaxHighlighter');
|
.addClass('OxSyntaxHighlighter');
|
||||||
|
|
||||||
|
renderSource();
|
||||||
|
|
||||||
|
function encodeToken(source, token) {
|
||||||
|
var linebreak = '<br/>',
|
||||||
|
tab = Ox.repeat(' ', self.options.tabLength);
|
||||||
|
if (self.options.showLinebreaks) {
|
||||||
|
if (token.type == 'linebreak') {
|
||||||
|
linebreak = '\u21A9' + linebreak;
|
||||||
|
} else {
|
||||||
|
linebreak = '<span class="OxLinebreak">\u21A9</span>' + linebreak;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self.options.showTabs) {
|
||||||
|
tab = '<span class="OxTab">\u2192' + tab.substr(6) + '</span>';
|
||||||
|
}
|
||||||
|
return Ox.encodeHTML(source)
|
||||||
|
.replace(/ /g, ' ')
|
||||||
|
.replace(/\t/g, tab)
|
||||||
|
.replace(/\n/g, linebreak);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderSource() {
|
||||||
self.options.source = self.options.source
|
self.options.source = self.options.source
|
||||||
.replace(/\r\n/g, '\n')
|
.replace(/\r\n/g, '\n')
|
||||||
.replace(/\r/g, '\n');
|
.replace(/\r/g, '\n');
|
||||||
|
|
||||||
self.cursor = 0;
|
self.cursor = 0;
|
||||||
self.source = '';
|
self.source = '';
|
||||||
self.tokens = Ox.tokenize(self.options.source);
|
self.tokens = Ox.tokenize(self.options.source);
|
||||||
|
@ -65,15 +87,13 @@ Ox.SyntaxHighlighter = function(options, self) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.lines = self.source.split('<br/>');
|
self.lines = self.source.split('<br/>');
|
||||||
self.lineNumbersWidth = (
|
|
||||||
self.lines.length + self.options.offset - 1
|
|
||||||
).toString().length * 7;
|
|
||||||
|
|
||||||
|
that.empty();
|
||||||
|
if (self.options.showLineNumbers) {
|
||||||
self.$lineNumbers = new Ox.Element()
|
self.$lineNumbers = new Ox.Element()
|
||||||
.addClass('OxLineNumbers')
|
.addClass('OxLineNumbers')
|
||||||
.css({
|
.css({
|
||||||
display: 'table-cell',
|
display: 'table-cell',
|
||||||
width: self.lineNumbersWidth + 'px',
|
|
||||||
padding: '4px',
|
padding: '4px',
|
||||||
})
|
})
|
||||||
.html(
|
.html(
|
||||||
|
@ -82,6 +102,7 @@ Ox.SyntaxHighlighter = function(options, self) {
|
||||||
}).join('<br/>')
|
}).join('<br/>')
|
||||||
)
|
)
|
||||||
.appendTo(that);
|
.appendTo(that);
|
||||||
|
}
|
||||||
self.$source = new Ox.Element()
|
self.$source = new Ox.Element()
|
||||||
.addClass('OxSourceCode')
|
.addClass('OxSourceCode')
|
||||||
.css({
|
.css({
|
||||||
|
@ -90,28 +111,10 @@ Ox.SyntaxHighlighter = function(options, self) {
|
||||||
})
|
})
|
||||||
.html(self.source)
|
.html(self.source)
|
||||||
.appendTo(that);
|
.appendTo(that);
|
||||||
|
|
||||||
function encodeToken(source, token) {
|
|
||||||
var linebreak = '<br/>',
|
|
||||||
tab = Ox.repeat(' ', self.options.tabLength);
|
|
||||||
if (self.options.showLinebreaks) {
|
|
||||||
if (token.type == 'linebreak') {
|
|
||||||
linebreak = '\u21A9' + linebreak;
|
|
||||||
} else {
|
|
||||||
linebreak = '<span class="OxLinebreak">\u21A9</span>' + linebreak;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (self.options.showTabs) {
|
|
||||||
tab = '<span class="OxTab">\u2192' + tab.substr(6) + '</span>';
|
|
||||||
}
|
|
||||||
return Ox.encodeHTML(source)
|
|
||||||
.replace(/ /g, ' ')
|
|
||||||
.replace(/\t/g, tab)
|
|
||||||
.replace(/\n/g, linebreak);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.setOption = function() {
|
self.setOption = function(key, value) {
|
||||||
|
renderSource();
|
||||||
};
|
};
|
||||||
|
|
||||||
return that;
|
return that;
|
||||||
|
|
166
source/Ox.js
166
source/Ox.js
|
@ -73,7 +73,7 @@ Ox.print <f> Prints its arguments to the console
|
||||||
The string contains the timestamp, the name of the caller function, and
|
The string contains the timestamp, the name of the caller function, and
|
||||||
any arguments, separated by spaces
|
any arguments, separated by spaces
|
||||||
arg <*> any value
|
arg <*> any value
|
||||||
> Ox.print("foo").substr(-3)
|
> Ox.print('foo').split(' ').pop()
|
||||||
"foo"
|
"foo"
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
|
@ -289,7 +289,26 @@ Ox.clone = function(obj) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.count <f> Counts the occurences of values in an array, object or string
|
Ox.contains <f> Tests if a collection contains a value
|
||||||
|
> Ox.contains(['foo', 'bar'], 'foo')
|
||||||
|
true
|
||||||
|
> Ox.contains({foo: 'bar'}, 'bar')
|
||||||
|
true
|
||||||
|
> Ox.contains({foo: 'bar'}, 'foo')
|
||||||
|
false
|
||||||
|
> Ox.contains("foobar", "bar")
|
||||||
|
true
|
||||||
|
@*/
|
||||||
|
Ox.contains = function(col, val) {
|
||||||
|
/*
|
||||||
|
// fixme: rename to Ox.has or Ox.isIn?
|
||||||
|
// then it'd become convenient for arrays
|
||||||
|
*/
|
||||||
|
return (Ox.isObject(col) ? Ox.values(col) : col).indexOf(val) > -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.count <f> Counts the occurences of values in a collection
|
||||||
> Ox.count(['f', 'o', 'o'])
|
> Ox.count(['f', 'o', 'o'])
|
||||||
{f: 1, o: 2}
|
{f: 1, o: 2}
|
||||||
> Ox.count({a: 'f', b: 'o', c: 'o'})
|
> Ox.count({a: 'f', b: 'o', c: 'o'})
|
||||||
|
@ -330,7 +349,7 @@ Ox.each = function(obj, fn) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.every <f> Returns true if a condition holds for every element of a collection
|
Ox.every <f> Tests if every element of a collection satisfies a given condition
|
||||||
Unlike <code>[].every()</code>, <code>Ox.every()</code> works for arrays,
|
Unlike <code>[].every()</code>, <code>Ox.every()</code> works for arrays,
|
||||||
objects and strings.
|
objects and strings.
|
||||||
> Ox.every([0, 1, 2], function(v, i) { return i == v; })
|
> Ox.every([0, 1, 2], function(v, i) { return i == v; })
|
||||||
|
@ -436,13 +455,11 @@ Ox.forEach = function(obj, fn) {
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.getObjectById <f> Returns an array element with a given id
|
Ox.getObjectById <f> Returns an array element with a given id
|
||||||
|
> Ox.getObjectById([{id: "foo", title: "Foo"}, {id: "bar", title: "Bar"}], "foo")
|
||||||
|
{id: "foo", title: "Foo"}
|
||||||
@*/
|
@*/
|
||||||
// fixme: shouldn't this be getElementById() ?
|
// fixme: shouldn't this be getElementById() ?
|
||||||
Ox.getObjectById = function(arr, id) {
|
Ox.getObjectById = function(arr, id) {
|
||||||
/***
|
|
||||||
>>> Ox.getObjectById([{id: "foo", title: "Foo"}, {id: "bar", title: "Bar"}], "foo").title
|
|
||||||
"Foo"
|
|
||||||
***/
|
|
||||||
var ret = null;
|
var ret = null;
|
||||||
Ox.forEach(arr, function(v) {
|
Ox.forEach(arr, function(v) {
|
||||||
if (v.id == id) {
|
if (v.id == id) {
|
||||||
|
@ -455,13 +472,11 @@ Ox.getObjectById = function(arr, id) {
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.getPositionById <f> Returns the index of an array element with a given id
|
Ox.getPositionById <f> Returns the index of an array element with a given id
|
||||||
|
> Ox.getPositionById([{id: "foo", title: "Foo"}, {id: "bar", title: "Bar"}], "foo")
|
||||||
|
0
|
||||||
@*/
|
@*/
|
||||||
// fixme: shouldn't this be getIndexById() ?
|
// fixme: shouldn't this be getIndexById() ?
|
||||||
Ox.getPositionById = function(arr, id) {
|
Ox.getPositionById = function(arr, id) {
|
||||||
/***
|
|
||||||
>>> Ox.getPositionById([{id: "foo", title: "Foo"}, {id: "bar", title: "Bar"}], "bar")
|
|
||||||
1
|
|
||||||
***/
|
|
||||||
var ret = -1;
|
var ret = -1;
|
||||||
Ox.forEach(arr, function(v, i) {
|
Ox.forEach(arr, function(v, i) {
|
||||||
if (v.id == id) {
|
if (v.id == id) {
|
||||||
|
@ -543,6 +558,8 @@ Ox.isEmpty <f> Returns true if a collection is empty
|
||||||
true
|
true
|
||||||
> Ox.isEmpty('')
|
> Ox.isEmpty('')
|
||||||
true
|
true
|
||||||
|
> Ox.isEmpty(function() {})
|
||||||
|
true
|
||||||
@*/
|
@*/
|
||||||
Ox.isEmpty = function(val) {
|
Ox.isEmpty = function(val) {
|
||||||
return Ox.len(val) == 0;
|
return Ox.len(val) == 0;
|
||||||
|
@ -620,7 +637,7 @@ Ox.len = function(obj) {
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.loop <f> For-loop, functional-style
|
Ox.loop <f> For-loop, functional-style
|
||||||
Returning <code>false</code> from the iterater function acts like a
|
Returning <code>false</code> from the iterator function acts like a
|
||||||
<code>break</code> statement. Unlike a <code>for</code> loop,
|
<code>break</code> statement. Unlike a <code>for</code> loop,
|
||||||
<code>Ox.loop</code> doesn't leak its counter variable to the outer scope,
|
<code>Ox.loop</code> doesn't leak its counter variable to the outer scope,
|
||||||
but returns it.
|
but returns it.
|
||||||
|
@ -630,8 +647,10 @@ Ox.loop <f> For-loop, functional-style
|
||||||
equivalent to <code>for (var i = start; i < stop; i++)</code> or,
|
equivalent to <code>for (var i = start; i < stop; i++)</code> or,
|
||||||
if <code>start</code> is larger than <code>stop</code>,
|
if <code>start</code> is larger than <code>stop</code>,
|
||||||
<code>for (var i = start; i > stop; i--)</code>
|
<code>for (var i = start; i > stop; i--)</code>
|
||||||
(start, stop, step) -> <n> Next value
|
(start, stop, step, callback) -> <n> Next value
|
||||||
equivalent to <code>for (var i = start; i < stop; i += step)</code>
|
equivalent to <code>for (var i = start; i < stop; i += step)</code> or,
|
||||||
|
if <code>step</code> is negative,
|
||||||
|
<code>for (var i = start; i > stop; i += step)</code>
|
||||||
start <n> Start value
|
start <n> Start value
|
||||||
stop <n> Stop value (exclusive)
|
stop <n> Stop value (exclusive)
|
||||||
step <n> Step value
|
step <n> Step value
|
||||||
|
@ -919,8 +938,7 @@ Ox.values <f> Returns the values of a collection
|
||||||
[1, 3]
|
[1, 3]
|
||||||
@*/
|
@*/
|
||||||
Ox.values = function(col) {
|
Ox.values = function(col) {
|
||||||
// this happens to works for arrays and strings, but still:
|
// Ox.values(str) is identical to str.split('')
|
||||||
// Ox.values(arr) -> arr, Ox.values(str) -> str.split('')
|
|
||||||
var values = [];
|
var values = [];
|
||||||
Ox.forEach(col, function(val) {
|
Ox.forEach(col, function(val) {
|
||||||
values.push(val);
|
values.push(val);
|
||||||
|
@ -3614,7 +3632,9 @@ Ox.sinh = function(x) {
|
||||||
|
|
||||||
//@ Constants ------------------------------------------------------------------
|
//@ Constants ------------------------------------------------------------------
|
||||||
|
|
||||||
|
//@ Ox.MAX_LATITUDE <n> Maximum latitude of a Mercator projection
|
||||||
Ox.MAX_LATITUDE = Ox.deg(Math.atan(Ox.sinh(Math.PI)));
|
Ox.MAX_LATITUDE = Ox.deg(Math.atan(Ox.sinh(Math.PI)));
|
||||||
|
//@ Ox.MIN_LATITUDE <n> Minimum latitude of a Mercator projection
|
||||||
Ox.MIN_LATITUDE = -Ox.MAX_LATITUDE;
|
Ox.MIN_LATITUDE = -Ox.MAX_LATITUDE;
|
||||||
|
|
||||||
//@ Object ---------------------------------------------------------------------
|
//@ Object ---------------------------------------------------------------------
|
||||||
|
@ -3811,44 +3831,32 @@ Ox.char <f> Alias for String.fromCharCode
|
||||||
// fixme: add some mapping? like Ox.char(9, 13) or Ox.char([9, 13])?
|
// fixme: add some mapping? like Ox.char(9, 13) or Ox.char([9, 13])?
|
||||||
Ox.char = String.fromCharCode;
|
Ox.char = String.fromCharCode;
|
||||||
|
|
||||||
Ox.clean = function(str) {
|
/*@
|
||||||
/*
|
Ox.clean <f> Remove leading, trailing and double whitespace from a string
|
||||||
>>> Ox.clean("foo bar")
|
> Ox.clean("foo bar")
|
||||||
"foo bar"
|
"foo bar"
|
||||||
>>> Ox.clean(" foo bar ")
|
> Ox.clean(" foo bar ")
|
||||||
"foo bar"
|
"foo bar"
|
||||||
>>> Ox.clean(" foo \n bar ")
|
> Ox.clean(" foo \n bar ")
|
||||||
"foo\nbar"
|
"foo\nbar"
|
||||||
*/
|
@*/
|
||||||
|
Ox.clean = function(str) {
|
||||||
return Ox.map(str.split('\n'), function(str) {
|
return Ox.map(str.split('\n'), function(str) {
|
||||||
return Ox.trim(str.replace(/\s+/g, ' '));
|
return Ox.trim(str.replace(/\s+/g, ' '));
|
||||||
}).join('\n');
|
}).join('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
Ox.contains = function(str, chr) {
|
|
||||||
/*
|
|
||||||
>>> Ox.contains("foo", "bar")
|
|
||||||
false
|
|
||||||
>>> Ox.contains("foobar", "bar")
|
|
||||||
true
|
|
||||||
>>> Ox.contains(['foo', 'bar'], 'foo')
|
|
||||||
true
|
|
||||||
// fixme: rename to Ox.has or Ox.isIn?
|
|
||||||
// then it'd become convenient for arrays
|
|
||||||
*/
|
|
||||||
return str.indexOf(chr) > -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.endsWith <f> Checks if a string ends with a given substring
|
Ox.endsWith <f> Checks if a string ends with a given substring
|
||||||
While <code>Ox.endsWith('foobar', 'bar')</code> is longer than
|
If the substring is a string literal (and not a variable),
|
||||||
<code>/bar$/.test('foobar')</code>, <code>Ox.endsWith('foobar', bar)</code>
|
<code>/sub$/.test(str)</code> or <code>!!/sub$/(str)</code>
|
||||||
is shorter than <code>new RegExp(bar + '$').test('foobar')</code>.
|
is shorter than <code>Ox.ends(str, sub)</code>.
|
||||||
> Ox.endsWith('foobar', 'bar')
|
> Ox.endsWith('foobar', 'bar')
|
||||||
true
|
true
|
||||||
@*/
|
@*/
|
||||||
Ox.endsWith = function(str, sub) {
|
Ox.endsWith = function(str, sub) {
|
||||||
return new RegExp(sub + '$').test(str);
|
// fixme: rename to ends
|
||||||
|
return str.substr(str.length - sub.length) == sub;
|
||||||
};
|
};
|
||||||
|
|
||||||
Ox.highlight = function(txt, str) {
|
Ox.highlight = function(txt, str) {
|
||||||
|
@ -3928,23 +3936,27 @@ Ox.parsePath = function(str) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ox.repeat = function(obj, num) {
|
/*@
|
||||||
/*
|
Ox.repeat <f> Repeat a value multiple times
|
||||||
works for arrays, numbers and strings
|
Works for arrays, numbers and strings
|
||||||
>>> Ox.repeat(1, 3)
|
> Ox.repeat(1, 3)
|
||||||
"111"
|
"111"
|
||||||
>>> Ox.repeat("foo", 3)
|
> Ox.repeat("foo", 3)
|
||||||
"foofoofoo"
|
"foofoofoo"
|
||||||
>>> Ox.repeat([1, 2], 3)
|
> Ox.repeat([1, 2], 3)
|
||||||
[1, 2, 1, 2, 1, 2]
|
[1, 2, 1, 2, 1, 2]
|
||||||
*/
|
@*/
|
||||||
|
Ox.repeat = function(val, num) {
|
||||||
var ret;
|
var ret;
|
||||||
if (Ox.isArray(obj)) {
|
if (Ox.isArray(val)) {
|
||||||
ret = num >= 1 ? Ox.map(Ox.range(obj.length * num), function(v, i) {
|
ret = [];
|
||||||
return obj[i % obj.length]
|
if (num >= 1) {
|
||||||
}) : [];
|
Ox.loop(num, function() {
|
||||||
|
ret = Ox.merge(ret, val);
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = num >= 1 ? new Array(num + 1).join(obj.toString()) : '';
|
ret = num >= 1 ? new Array(num + 1).join(val.toString()) : '';
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
@ -3959,22 +3971,15 @@ Ox.reverse = function(str) {
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
Ox.startsWith <f> Checks if a string starts with a given substring
|
Ox.startsWith <f> Checks if a string starts with a given substring
|
||||||
While <code>Ox.startsWith('foobar', 'foo')</code> is longer than
|
If the substring is a string literal (and not a variable),
|
||||||
<code>/^foo/.test('foobar')</code>, <code>Ox.startsWith('foobar', foo)</code>
|
<code>/^sub/.test(str)</code> or <code>!!/^sub/(str)</code>
|
||||||
is shorter than <code>new RegExp('^' + foo).test('foobar')</code>.
|
is shorter than <code>Ox.starts(str, sub)</code>.
|
||||||
> Ox.endsWith('foobar', 'bar')
|
> Ox.startsWith('foobar', 'foo')
|
||||||
true
|
true
|
||||||
@*/
|
@*/
|
||||||
Ox.startsWith = function(str, sub) {
|
Ox.startsWith = function(str, sub) {
|
||||||
/*
|
// fixme: rename to starts
|
||||||
>>> Ox.startsWith("foobar", "foo")
|
return str.substr(0, sub.length) == sub;
|
||||||
true
|
|
||||||
// fixme:
|
|
||||||
// !!(/^sub/(str)) is shorter than
|
|
||||||
// Ox.startsWith(str, sub) anyway
|
|
||||||
// new RegExp('^' + sub).test(str) is longer though...
|
|
||||||
*/
|
|
||||||
return new RegExp('^' + sub).test(str);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
|
@ -3983,26 +3988,29 @@ Ox.stripTags <f> Strips HTML tags from a string
|
||||||
'foo'
|
'foo'
|
||||||
@*/
|
@*/
|
||||||
Ox.stripTags = function(str) {
|
Ox.stripTags = function(str) {
|
||||||
return str.replace(/(<.*?>)/g, '');
|
return str.replace(/<.*?>/g, '');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.substr <f> A better <code>substr</code>
|
||||||
|
> Ox.substr('foobar', 1)
|
||||||
|
"oobar"
|
||||||
|
> Ox.substr('foobar', -1)
|
||||||
|
"r"
|
||||||
|
> Ox.substr('foobar', 1, 5)
|
||||||
|
"ooba"
|
||||||
|
> Ox.substr('foobar', 1, -1)
|
||||||
|
"ooba"
|
||||||
|
> Ox.substr('foobar', -5, 5)
|
||||||
|
"ooba"
|
||||||
|
> Ox.substr('foobar', -5, -1)
|
||||||
|
"ooba"
|
||||||
|
@*/
|
||||||
Ox.substr = function(str, start, stop) {
|
Ox.substr = function(str, start, stop) {
|
||||||
/***
|
/***
|
||||||
|
// fixme: needed?
|
||||||
Ox.substr behaves like str[start:stop] in Python
|
Ox.substr behaves like str[start:stop] in Python
|
||||||
(or like str.substring() with negative values for stop)
|
(or like str.substring() with negative values for stop)
|
||||||
// fixme: needed?
|
|
||||||
>>> Ox.substr('foobar', 1)
|
|
||||||
"oobar"
|
|
||||||
>>> Ox.substr('foobar', -1)
|
|
||||||
"r"
|
|
||||||
>>> Ox.substr('foobar', 1, 3)
|
|
||||||
"oo"
|
|
||||||
>>> Ox.substr('foobar', -3, 5)
|
|
||||||
"ba"
|
|
||||||
>>> Ox.substr('foobar', 1, -2)
|
|
||||||
"oob"
|
|
||||||
>>> Ox.substr('foobar', -4, -1)
|
|
||||||
"oba"
|
|
||||||
***/
|
***/
|
||||||
stop = Ox.isUndefined(stop) ? str.length : stop;
|
stop = Ox.isUndefined(stop) ? str.length : stop;
|
||||||
return str.substring(
|
return str.substring(
|
||||||
|
|
Loading…
Add table
Reference in a new issue