mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-06-26 16:08:34 +02:00
RAWRRRR next level done
This commit is contained in:
parent
108ab07f93
commit
e4cf2f6faa
6 changed files with 159 additions and 78 deletions
157
build/bundle.js
157
build/bundle.js
|
@ -6508,7 +6508,7 @@ var getLocale = exports.getLocale = function() {
|
||||||
// things like "{branchName} does not exist".
|
// things like "{branchName} does not exist".
|
||||||
var templateSettings = _.clone(_.templateSettings);
|
var templateSettings = _.clone(_.templateSettings);
|
||||||
templateSettings.interpolate = /\{(.+?)\}/g;
|
templateSettings.interpolate = /\{(.+?)\}/g;
|
||||||
var template = function(str, params) {
|
var template = exports.template = function(str, params) {
|
||||||
return _.template(str, params, templateSettings);
|
return _.template(str, params, templateSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6599,15 +6599,37 @@ var getStartDialog = exports.getStartDialog = function(level) {
|
||||||
});
|
});
|
||||||
|
|
||||||
require.define("/src/js/intl/strings.js",function(require,module,exports,__dirname,__filename,process,global){exports.strings = {
|
require.define("/src/js/intl/strings.js",function(require,module,exports,__dirname,__filename,process,global){exports.strings = {
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-finished': {
|
||||||
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
|
'en_US': 'Wow! You finished the last level, great!'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-next': {
|
||||||
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
|
'en_US': 'Would you like to move onto *"{nextLevel}"*, the next level?'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-win': {
|
||||||
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
|
'en_US': 'Awesome! You matched or exceeded our solution.'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-lose': {
|
||||||
|
'__desc__': 'When the user entered more commands than our best, encourage them to do better',
|
||||||
|
'en_US': 'See if you can whittle it down to {best} :D'
|
||||||
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'git-status-detached': {
|
'git-status-detached': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'Detached head!'
|
'en_US': 'Detached head!'
|
||||||
},
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'git-status-onbranch': {
|
'git-status-onbranch': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'On branch {branch}'
|
'en_US': 'On branch {branch}'
|
||||||
},
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'git-status-readytocommit': {
|
'git-status-readytocommit': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'Ready to commit! (as always in this demo)'
|
'en_US': 'Ready to commit! (as always in this demo)'
|
||||||
|
@ -10965,43 +10987,32 @@ var NextLevelConfirm = ConfirmCancelTerminal.extend({
|
||||||
var nextLevelName = (options.nextLevel) ?
|
var nextLevelName = (options.nextLevel) ?
|
||||||
intl.getName(options.nextLevel) :
|
intl.getName(options.nextLevel) :
|
||||||
'';
|
'';
|
||||||
var pluralNumCommands = (options.numCommands == 1) ? '' : 's';
|
|
||||||
var pluralBest = (options.best == 1) ? '' : 's';
|
|
||||||
|
|
||||||
var markdowns = [
|
// lol hax
|
||||||
'## Great Job!!',
|
var markdowns = intl.getDialog(require('../dialogs/nextLevel'))[0].options.markdowns;
|
||||||
'',
|
var markdown = markdowns.join('\n');
|
||||||
'You solved the level in **' + options.numCommands + '** command' + pluralNumCommands + '; ',
|
markdown = intl.template(markdown, {
|
||||||
'our solution uses ' + options.best + '. '
|
numCommands: options.numCommands,
|
||||||
];
|
best: options.best
|
||||||
|
});
|
||||||
|
|
||||||
if (options.numCommands <= options.best) {
|
if (options.numCommands <= options.best) {
|
||||||
markdowns.push(
|
markdown = markdown + '\n\n' + intl.str('finish-dialog-win');
|
||||||
'Awesome! You matched or exceeded our solution. '
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
markdowns.push(
|
markdown = markdown + '\n\n' + intl.str('finish-dialog-lose', {best: options.best});
|
||||||
'See if you can whittle it down to ' + options.best + ' command' + pluralBest + ' :D '
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
markdown = markdown + '\n\n';
|
||||||
if (options.nextLevel) {
|
if (options.nextLevel) {
|
||||||
markdowns = markdowns.concat([
|
markdown = markdown + intl.str('finish-dialog-next', {nextLevel: nextLevelName});
|
||||||
'',
|
|
||||||
'Would you like to move onto "' +
|
|
||||||
nextLevelName + '", the next level?'
|
|
||||||
]);
|
|
||||||
} else {
|
} else {
|
||||||
markdowns = markdowns.concat([
|
markdown = markdown + intl.str('finish-dialog-finished');
|
||||||
'',
|
|
||||||
'Wow!!! You finished the last level, congratulations!'
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options = _.extend(
|
options = _.extend(
|
||||||
{},
|
{},
|
||||||
options,
|
options,
|
||||||
{ markdowns: markdowns }
|
{ markdown: markdown }
|
||||||
);
|
);
|
||||||
|
|
||||||
NextLevelConfirm.__super__.initialize.apply(this, [options]);
|
NextLevelConfirm.__super__.initialize.apply(this, [options]);
|
||||||
|
@ -13419,6 +13430,23 @@ EventEmitter.prototype.listeners = function(type) {
|
||||||
return this._events[type];
|
return this._events[type];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
require.define("/src/js/dialogs/nextLevel.js",function(require,module,exports,__dirname,__filename,process,global){exports.dialog = {
|
||||||
|
'en_US': [{
|
||||||
|
type: 'ModalAlert',
|
||||||
|
options: {
|
||||||
|
markdowns: [
|
||||||
|
'## Great Job!!',
|
||||||
|
'',
|
||||||
|
'You solved the level in *{numCommands}* command(s); ',
|
||||||
|
'our solution uses {best}.'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
require.define("/src/js/models/commandModel.js",function(require,module,exports,__dirname,__filename,process,global){var _ = require('underscore');
|
require.define("/src/js/models/commandModel.js",function(require,module,exports,__dirname,__filename,process,global){var _ = require('underscore');
|
||||||
|
@ -20564,6 +20592,24 @@ require.define("/src/js/dialogs/levelBuilder.js",function(require,module,exports
|
||||||
});
|
});
|
||||||
require("/src/js/dialogs/levelBuilder.js");
|
require("/src/js/dialogs/levelBuilder.js");
|
||||||
|
|
||||||
|
require.define("/src/js/dialogs/nextLevel.js",function(require,module,exports,__dirname,__filename,process,global){exports.dialog = {
|
||||||
|
'en_US': [{
|
||||||
|
type: 'ModalAlert',
|
||||||
|
options: {
|
||||||
|
markdowns: [
|
||||||
|
'## Great Job!!',
|
||||||
|
'',
|
||||||
|
'You solved the level in *{numCommands}* command(s); ',
|
||||||
|
'our solution uses {best}.'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
require("/src/js/dialogs/nextLevel.js");
|
||||||
|
|
||||||
require.define("/src/js/dialogs/sandbox.js",function(require,module,exports,__dirname,__filename,process,global){exports.dialog = {
|
require.define("/src/js/dialogs/sandbox.js",function(require,module,exports,__dirname,__filename,process,global){exports.dialog = {
|
||||||
'en_US': [{
|
'en_US': [{
|
||||||
type: 'ModalAlert',
|
type: 'ModalAlert',
|
||||||
|
@ -23047,7 +23093,7 @@ var getLocale = exports.getLocale = function() {
|
||||||
// things like "{branchName} does not exist".
|
// things like "{branchName} does not exist".
|
||||||
var templateSettings = _.clone(_.templateSettings);
|
var templateSettings = _.clone(_.templateSettings);
|
||||||
templateSettings.interpolate = /\{(.+?)\}/g;
|
templateSettings.interpolate = /\{(.+?)\}/g;
|
||||||
var template = function(str, params) {
|
var template = exports.template = function(str, params) {
|
||||||
return _.template(str, params, templateSettings);
|
return _.template(str, params, templateSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23139,15 +23185,37 @@ var getStartDialog = exports.getStartDialog = function(level) {
|
||||||
require("/src/js/intl/index.js");
|
require("/src/js/intl/index.js");
|
||||||
|
|
||||||
require.define("/src/js/intl/strings.js",function(require,module,exports,__dirname,__filename,process,global){exports.strings = {
|
require.define("/src/js/intl/strings.js",function(require,module,exports,__dirname,__filename,process,global){exports.strings = {
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-finished': {
|
||||||
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
|
'en_US': 'Wow! You finished the last level, great!'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-next': {
|
||||||
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
|
'en_US': 'Would you like to move onto *"{nextLevel}"*, the next level?'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-win': {
|
||||||
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
|
'en_US': 'Awesome! You matched or exceeded our solution.'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-lose': {
|
||||||
|
'__desc__': 'When the user entered more commands than our best, encourage them to do better',
|
||||||
|
'en_US': 'See if you can whittle it down to {best} :D'
|
||||||
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'git-status-detached': {
|
'git-status-detached': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'Detached head!'
|
'en_US': 'Detached head!'
|
||||||
},
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'git-status-onbranch': {
|
'git-status-onbranch': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'On branch {branch}'
|
'en_US': 'On branch {branch}'
|
||||||
},
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'git-status-readytocommit': {
|
'git-status-readytocommit': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'Ready to commit! (as always in this demo)'
|
'en_US': 'Ready to commit! (as always in this demo)'
|
||||||
|
@ -27476,43 +27544,32 @@ var NextLevelConfirm = ConfirmCancelTerminal.extend({
|
||||||
var nextLevelName = (options.nextLevel) ?
|
var nextLevelName = (options.nextLevel) ?
|
||||||
intl.getName(options.nextLevel) :
|
intl.getName(options.nextLevel) :
|
||||||
'';
|
'';
|
||||||
var pluralNumCommands = (options.numCommands == 1) ? '' : 's';
|
|
||||||
var pluralBest = (options.best == 1) ? '' : 's';
|
|
||||||
|
|
||||||
var markdowns = [
|
// lol hax
|
||||||
'## Great Job!!',
|
var markdowns = intl.getDialog(require('../dialogs/nextLevel'))[0].options.markdowns;
|
||||||
'',
|
var markdown = markdowns.join('\n');
|
||||||
'You solved the level in **' + options.numCommands + '** command' + pluralNumCommands + '; ',
|
markdown = intl.template(markdown, {
|
||||||
'our solution uses ' + options.best + '. '
|
numCommands: options.numCommands,
|
||||||
];
|
best: options.best
|
||||||
|
});
|
||||||
|
|
||||||
if (options.numCommands <= options.best) {
|
if (options.numCommands <= options.best) {
|
||||||
markdowns.push(
|
markdown = markdown + '\n\n' + intl.str('finish-dialog-win');
|
||||||
'Awesome! You matched or exceeded our solution. '
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
markdowns.push(
|
markdown = markdown + '\n\n' + intl.str('finish-dialog-lose', {best: options.best});
|
||||||
'See if you can whittle it down to ' + options.best + ' command' + pluralBest + ' :D '
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
markdown = markdown + '\n\n';
|
||||||
if (options.nextLevel) {
|
if (options.nextLevel) {
|
||||||
markdowns = markdowns.concat([
|
markdown = markdown + intl.str('finish-dialog-next', {nextLevel: nextLevelName});
|
||||||
'',
|
|
||||||
'Would you like to move onto "' +
|
|
||||||
nextLevelName + '", the next level?'
|
|
||||||
]);
|
|
||||||
} else {
|
} else {
|
||||||
markdowns = markdowns.concat([
|
markdown = markdown + intl.str('finish-dialog-finished');
|
||||||
'',
|
|
||||||
'Wow!!! You finished the last level, congratulations!'
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options = _.extend(
|
options = _.extend(
|
||||||
{},
|
{},
|
||||||
options,
|
options,
|
||||||
{ markdowns: markdowns }
|
{ markdown: markdown }
|
||||||
);
|
);
|
||||||
|
|
||||||
NextLevelConfirm.__super__.initialize.apply(this, [options]);
|
NextLevelConfirm.__super__.initialize.apply(this, [options]);
|
||||||
|
|
14
src/js/dialogs/nextLevel.js
Normal file
14
src/js/dialogs/nextLevel.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
exports.dialog = {
|
||||||
|
'en_US': [{
|
||||||
|
type: 'ModalAlert',
|
||||||
|
options: {
|
||||||
|
markdowns: [
|
||||||
|
'## Great Job!!',
|
||||||
|
'',
|
||||||
|
'You solved the level in *{numCommands}* command(s); ',
|
||||||
|
'our solution uses {best}.'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
|
@ -19,7 +19,7 @@ var getLocale = exports.getLocale = function() {
|
||||||
// things like "{branchName} does not exist".
|
// things like "{branchName} does not exist".
|
||||||
var templateSettings = _.clone(_.templateSettings);
|
var templateSettings = _.clone(_.templateSettings);
|
||||||
templateSettings.interpolate = /\{(.+?)\}/g;
|
templateSettings.interpolate = /\{(.+?)\}/g;
|
||||||
var template = function(str, params) {
|
var template = exports.template = function(str, params) {
|
||||||
return _.template(str, params, templateSettings);
|
return _.template(str, params, templateSettings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,35 @@
|
||||||
exports.strings = {
|
exports.strings = {
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-finished': {
|
||||||
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
|
'en_US': 'Wow! You finished the last level, great!'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-next': {
|
||||||
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
|
'en_US': 'Would you like to move onto *"{nextLevel}"*, the next level?'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-win': {
|
||||||
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
|
'en_US': 'Awesome! You matched or exceeded our solution.'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'finish-dialog-lose': {
|
||||||
|
'__desc__': 'When the user entered more commands than our best, encourage them to do better',
|
||||||
|
'en_US': 'See if you can whittle it down to {best} :D'
|
||||||
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'git-status-detached': {
|
'git-status-detached': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'Detached head!'
|
'en_US': 'Detached head!'
|
||||||
},
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'git-status-onbranch': {
|
'git-status-onbranch': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'On branch {branch}'
|
'en_US': 'On branch {branch}'
|
||||||
},
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'git-status-readytocommit': {
|
'git-status-readytocommit': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'Ready to commit! (as always in this demo)'
|
'en_US': 'Ready to commit! (as always in this demo)'
|
||||||
|
|
|
@ -429,43 +429,32 @@ var NextLevelConfirm = ConfirmCancelTerminal.extend({
|
||||||
var nextLevelName = (options.nextLevel) ?
|
var nextLevelName = (options.nextLevel) ?
|
||||||
intl.getName(options.nextLevel) :
|
intl.getName(options.nextLevel) :
|
||||||
'';
|
'';
|
||||||
var pluralNumCommands = (options.numCommands == 1) ? '' : 's';
|
|
||||||
var pluralBest = (options.best == 1) ? '' : 's';
|
|
||||||
|
|
||||||
var markdowns = [
|
// lol hax
|
||||||
'## Great Job!!',
|
var markdowns = intl.getDialog(require('../dialogs/nextLevel'))[0].options.markdowns;
|
||||||
'',
|
var markdown = markdowns.join('\n');
|
||||||
'You solved the level in **' + options.numCommands + '** command' + pluralNumCommands + '; ',
|
markdown = intl.template(markdown, {
|
||||||
'our solution uses ' + options.best + '. '
|
numCommands: options.numCommands,
|
||||||
];
|
best: options.best
|
||||||
|
});
|
||||||
|
|
||||||
if (options.numCommands <= options.best) {
|
if (options.numCommands <= options.best) {
|
||||||
markdowns.push(
|
markdown = markdown + '\n\n' + intl.str('finish-dialog-win');
|
||||||
'Awesome! You matched or exceeded our solution. '
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
markdowns.push(
|
markdown = markdown + '\n\n' + intl.str('finish-dialog-lose', {best: options.best});
|
||||||
'See if you can whittle it down to ' + options.best + ' command' + pluralBest + ' :D '
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
markdown = markdown + '\n\n';
|
||||||
if (options.nextLevel) {
|
if (options.nextLevel) {
|
||||||
markdowns = markdowns.concat([
|
markdown = markdown + intl.str('finish-dialog-next', {nextLevel: nextLevelName});
|
||||||
'',
|
|
||||||
'Would you like to move onto "' +
|
|
||||||
nextLevelName + '", the next level?'
|
|
||||||
]);
|
|
||||||
} else {
|
} else {
|
||||||
markdowns = markdowns.concat([
|
markdown = markdown + intl.str('finish-dialog-finished');
|
||||||
'',
|
|
||||||
'Wow!!! You finished the last level, congratulations!'
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options = _.extend(
|
options = _.extend(
|
||||||
{},
|
{},
|
||||||
options,
|
options,
|
||||||
{ markdowns: markdowns }
|
{ markdown: markdown }
|
||||||
);
|
);
|
||||||
|
|
||||||
NextLevelConfirm.__super__.initialize.apply(this, [options]);
|
NextLevelConfirm.__super__.initialize.apply(this, [options]);
|
||||||
|
|
5
todo.txt
5
todo.txt
|
@ -4,14 +4,11 @@ Mega Things
|
||||||
|
|
||||||
Intl TODO
|
Intl TODO
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
[ ] git/index.js translation -- rest of the strings
|
|
||||||
[ ] next level confirm translation
|
|
||||||
[ ] rest of views/index translation
|
[ ] rest of views/index translation
|
||||||
|
|
||||||
Big Things
|
Big Things
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
[ ] compare settings for a level!!! integrated into builder...
|
[ ] compare settings for a level!!! integrated into builder...
|
||||||
[ ] rebase -i solution demonstration (blink and fade thing?)
|
|
||||||
[ ] hash agnotisc comparison with asserts for ammends
|
[ ] hash agnotisc comparison with asserts for ammends
|
||||||
[ ] tree pruning
|
[ ] tree pruning
|
||||||
|
|
||||||
|
@ -38,6 +35,8 @@ Ideas for cleaning
|
||||||
Done things:
|
Done things:
|
||||||
(I only started this on Dec 17th 2012 to get a better sense of what was done)
|
(I only started this on Dec 17th 2012 to get a better sense of what was done)
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
[x] git/index.js translation -- rest of the strings
|
||||||
|
[x] next level confirm translation
|
||||||
[x] fix clickthrough when goal is shown
|
[x] fix clickthrough when goal is shown
|
||||||
[x] hash agnostic comparison
|
[x] hash agnostic comparison
|
||||||
[x] get automated SHA hash appending in the html source :OOOOO... template? or what?t
|
[x] get automated SHA hash appending in the html source :OOOOO... template? or what?t
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue