diff --git a/.github/workflows/deploy.yml b/.github/workflows/mol.yml similarity index 76% rename from .github/workflows/deploy.yml rename to .github/workflows/mol.yml index 6e0b7fb043b..985fe8e14a5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/mol.yml @@ -1,4 +1,4 @@ -name: Deploy +name: $mol on: workflow_dispatch: @@ -42,12 +42,12 @@ jobs: if: github.ref == 'refs/heads/master' runs-on: ubuntu-latest steps: - - env: - GITHUB_TOKEN: ${{ secrets.GH_PAT }} - INPUTS_CLIENT_PAYLOAD: '{"repository":${{ toJson(github.event.repository.name) }}}' - INPUTS_EVENT_TYPE: dependency_changed - INPUTS_REPOSITORY: ${{ matrix.repo }} - uses: rekgrpth/github-repository-dispatch-shell-action@v1 + - uses: peter-evans/repository-dispatch@v3 + with: + token: ${{ secrets.GH_PAT }} + repository: ${{ matrix.repo }} + event-type: dependency_changed + client-payload: '{"repository":${{ toJson(github.event.repository.name) }}}' strategy: matrix: repo: diff --git a/build/build.node.ts b/build/build.node.ts index 38aa26ab3a8..624a4cf157e 100644 --- a/build/build.node.ts +++ b/build/build.node.ts @@ -630,7 +630,7 @@ namespace $ { @ $mol_mem gitVersion() { - return this.$.$mol_run({ command: 'git version', dir: '.' }).stdout.toString().trim().match(/.*\s+([\d\.]+)$/)?.[1] ?? '' + return this.$.$mol_run({ command: 'git version', dir: '.' }).stdout.toString().trim().match(/.*\s+([\d\.]+\d+)/)?.[1] ?? '' } gitDeepenSupported() { @@ -641,13 +641,13 @@ namespace $ { gitPull(path: string) { const args = [] as string[] - if ( ! this.interactive() ) { + if ( ! this.interactive() && this.gitDeepenSupported() ) { // depth и deepen не годятся для локальной разработки, поэтому оставляем ограничение глубины пула только для CI // --depth=1 в сочетании с сабмодулями обрезает историю, кроме первого коммита - // --deepen=1 в git-конфиге сабмодуля выставляет bare=true, после этого все команды падают с сообщением + // --deepen=1, если не сделать unset GIT_DIR, в git-конфиге сабмодуля выставляет bare=true, после этого все команды падают с сообщением // warning: core.bare and core.worktree do not make sense // fatal: unable to set up work tree using invalid config - args.push( this.gitDeepenSupported() ? '--deepen=1' : '--depth=1' ) + args.push( '--deepen=1' ) } return this.run_safe( { command: ['git', 'pull', ...args], dir: path } ) } diff --git a/format/format.view.ts b/format/format.view.ts index faf0eeb903e..a61ba819fa5 100644 --- a/format/format.view.ts +++ b/format/format.view.ts @@ -19,8 +19,11 @@ namespace $.$$ { const mask = this.mask( filtered ) if( ( prev?.[0] ?? 0 ) >= from ) return [ from, to ] - - const lastAllow = ( value.length - [ ... value ].reverse().findIndex( letter => allow.includes( letter ) ) )%(value.length+1) + + const lastAllow = ( + value.length - [ ... value ].reverse().findIndex( letter => allow.includes( letter ) ) + ) % ( value.length + 1 ) + if( lastAllow < from ) { from = to = lastAllow } @@ -29,7 +32,7 @@ namespace $.$$ { ++ from ++ to } - + return [ from, to ] } diff --git a/index.html b/index.html deleted file mode 100644 index e13ea44c6b7..00000000000 --- a/index.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/number/number.view.ts b/number/number.view.ts index b1360dbc4f9..ba3e2a7d6e2 100644 --- a/number/number.view.ts +++ b/number/number.view.ts @@ -6,15 +6,13 @@ namespace $.$$ { */ export class $mol_number extends $.$mol_number { - value_limited( next? : any ) : number { - if ( next === undefined ) return this.value() - if ( next === '' ) return this.value( Number.NaN ) + value_limited( val? : number ) : number { + if (Number.isNaN( val )) return this.value( val ) + if ( val === undefined ) return this.value() const min = this.value_min() const max = this.value_max() - const val = Number( next ) - if( val < min ) return this.value( min ) if( val > max ) return this.value( max ) @@ -28,23 +26,71 @@ namespace $.$$ { override event_inc( next? : Event ) { this.value_limited( ( this.value_limited() || 0 ) + this.precision_change() ) } - - override value_string( next? : string ) { - const next_num = this.value_limited( next ) - const precisionView = this.precision_view() + round(val: number) { + if (Number.isNaN(val)) return '' + if( val === 0 ) return '0' + if( !val ) return '' + + const precision_view = this.precision_view() - if( next_num === 0 ) return '0' - if( !next_num ) return '' + if (! precision_view) return val.toFixed() - if( precisionView >= 1 ) { - return ( next_num / precisionView ).toFixed() + if( precision_view >= 1 ) { + return ( val / precision_view ).toFixed() } else { - const fixedNumber = Math.log10( 1 / precisionView ) - return next_num.toFixed( Math.ceil( fixedNumber ) ) + const fixed_number = Math.log10( 1 / precision_view ) + return val.toFixed( Math.ceil( fixed_number ) ) } } - + + @ $mol_mem + override value_string( next? : string ): string { + // Вытягиваем value + // Если кто-то поменяет из вне value, value_string надо обновить + const current = this.round( this.value_limited() ) + if (next === undefined) return current + + const precision = this.precision_view() + + // Точку в конце поставить нельзя, если precision_view целое число > 0 + if ( precision - Math.floor(precision) === 0 ) next = next.replace(/[.,]/g, '') + + // Запятые меняем на точки, удаляем не-цифры и не-точки и лишние ноли в начале целой части. + // Минус получится ввести только в начале. + next = (this.value_min() < 0 && next.startsWith('-') ? '-' : '') + + next.replace(/,/g, '.').replace(/[^\d\.]/g, '').replace(/^0{2,}/, '0') + + let dot_pos = next.indexOf('.') + + if (dot_pos !== -1) { + const prev = $mol_wire_probe(() => this.value_string()) ?? '' + const dot_pos_prev = prev.indexOf('.') + // Определяем где относительно предыдущей точки юзер поставил новую + if (dot_pos_prev === dot_pos) dot_pos = next.lastIndexOf('.') + + // Из частей до и после новой точки старую точку удаляем + const frac = next.slice(dot_pos + 1).replace(/\./g, '') + + // Если точка идет первой, перед ней пишем 0, что бы форматирование выглядело нормально в mask + next = (next.slice(0, dot_pos) || '0').replace(/\./g, '') + '.' + frac + } + + // Оставляем старое значение в value есть сочетание, приводящие к NaN, например -. + if ( Number.isNaN(Number(next)) ) return next + + if ( next.endsWith('.') ) return next + if ( next.endsWith('-') ) return next + + // Если пустая строка - сетим NaN + // Применяем округления. + this.value_limited(Number(next || Number.NaN)) + + // Возвращаем все-равно не нормализованное значение + // Иначе нельзя ввести будет 10, если min/max 5..10 + return next + } + @ $mol_mem override dec_enabled() : boolean { return this.enabled() && ( diff --git a/page/page.view.tree b/page/page.view.tree index d383c52e94d..efbe615a1c8 100644 --- a/page/page.view.tree +++ b/page/page.view.tree @@ -1,6 +1,6 @@ $mol_page $mol_view dom_name \article - field * + attr * ^ tabIndex <= tabindex -1 sub / diff --git a/portion/portion.view.tree b/portion/portion.view.tree index c9aa3826825..acd3949ce88 100644 --- a/portion/portion.view.tree +++ b/portion/portion.view.tree @@ -6,5 +6,5 @@ $mol_portion_indicator $mol_view $mol_portion $mol_view portion 0 sub / - <= indicator $mol_portion_indicator + <= Indicator $mol_portion_indicator width_style <= indicator_width_style \0 diff --git a/state/arg/arg.node.test.ts b/state/arg/arg.node.test.ts new file mode 100644 index 00000000000..78b0236702e --- /dev/null +++ b/state/arg/arg.node.test.ts @@ -0,0 +1,20 @@ +namespace $ { + + $mol_test_mocks.push( context => { + class $mol_state_arg_mock extends $mol_state_arg { + + static $ = context + + @ $mol_mem + static href( next? : string ) { return next || '' } + + @ $mol_action + static go( next : { [ key : string ] : string | null } ) { + this.href( this.link( next ) ) + } + + } + context.$mol_state_arg = $mol_state_arg_mock + } ) + +} diff --git a/state/arg/arg.web.test.ts b/state/arg/arg.web.test.ts index f921dfcceac..383b678b0af 100644 --- a/state/arg/arg.web.test.ts +++ b/state/arg/arg.web.test.ts @@ -8,6 +8,11 @@ namespace $ { @ $mol_mem static href( next? : string ) { return next || '' } + @ $mol_action + static go( next : { [ key : string ] : string | null } ) { + this.href( this.link( next ) ) + } + } context.$mol_state_arg = $mol_state_arg_mock } ) @@ -17,7 +22,7 @@ namespace $ { 'args as dictionary'( $ ) { $.$mol_state_arg.href( '#!foo=bar/xxx' ) - $mol_assert_like( $.$mol_state_arg.dict() , { foo : 'bar' , xxx : '' } ) + $mol_assert_equal( $.$mol_state_arg.dict() , { foo : 'bar' , xxx : '' } ) $.$mol_state_arg.dict({ foo : null , yyy : '' , lol : '123' }) $mol_assert_equal( $.$mol_state_arg.href().replace( /.*#/ , '#' ) , '#!yyy/lol=123' ) diff --git a/syntax2/md/md.ts b/syntax2/md/md.ts index 077d7064328..9873f91f5bd 100644 --- a/syntax2/md/md.ts +++ b/syntax2/md/md.ts @@ -33,8 +33,8 @@ namespace $ { 'code-docs' : /\/\/\/.*?$/ , 'code-comment-block' : /(?:\/\*[^]*?\*\/|\/\+[^]*?\+\/|)/ , 'code-link' : /(?:\w+:\/\/|#)\S+?(?=\s|\\\\|""|$)/ , - 'code-comment-inline' : /\/\/.*?(?:$|\/\/)/ , - 'code-string' : /(?:".*?"|'.*?'|`.*?`|\/.+?\/[dygimsu]*(?!\p{Letter})|(?:^|[ \t])\\[^\n]*\n)/u , + 'code-comment-inline' : /\/\/.*?(?:$|\/\/)|- \\.*/ , + 'code-string' : /(?:".*?"|'.*?'|`.*?`| ?\\\\.+?\\\\|\/.+?\/[dygimsu]*(?!\p{Letter})|[ \t]*\\[^\n]*)/u , 'code-number' : /[+-]?(?:\d*\.)?\d+\w*/ , 'code-call' : /\.?\w+ *(?=\()/ , 'code-sexpr' : /\((\w+ )/ , @@ -42,7 +42,7 @@ namespace $ { 'code-keyword' : /\b(throw|readonly|unknown|keyof|typeof|never|from|class|struct|interface|type|function|extends|implements|module|namespace|import|export|include|require|var|val|let|const|for|do|while|until|in|out|of|new|if|then|else|switch|case|this|return|async|await|yield|try|catch|break|continue|get|set|public|private|protected|string|boolean|number|null|undefined|true|false|void|int|float|ref)\b/ , 'code-global' : /[$]+\w*|\b[A-Z][a-z0-9]+[A-Z]\w*/ , 'code-word' : /\w+/ , - 'code-decorator' : /@\s*\S+/ , + 'code-decorator' : /@.+/ , 'code-tag' : /<\/?[\w-]+\/?>?|&\w+;/ , 'code-punctuation' : /[\-\[\]\{\}\(\)<=>~!\?@#%&\*_\+\\\/\|;:\.,\^]+?/ , }) diff --git a/view/view/view.ts b/view/view/view.ts index d0b1a16192b..bdbc2109246 100644 --- a/view/view/view.ts +++ b/view/view/view.ts @@ -1,6 +1,6 @@ namespace $ { - export type $mol_view_content = $mol_view|Node|string|number|boolean + export type $mol_view_content = $mol_view|Node|string|number|boolean|null export function $mol_view_visible_width() { return $mol_window.size().width @@ -86,7 +86,7 @@ namespace $ { /// Raw child views sub() { - return [] as readonly ($mol_view|Node|string|number|boolean)[] + return [] as readonly $mol_view_content[] } /// Visible sub views with defined ambient context diff --git a/wait/rest/rest.test.ts b/wait/rest/rest.test.ts new file mode 100644 index 00000000000..cad9dbb1f32 --- /dev/null +++ b/wait/rest/rest.test.ts @@ -0,0 +1,8 @@ +namespace $.$$ { + + $mol_test_mocks.push( $ => { + $.$mol_wait_timeout = function $mol_wait_timeout_mock( this: $, timeout: number ) { } + $.$mol_wait_timeout_async = async function $mol_wait_timeout_async_mock( this: $, timeout: number ) {} + } ) + +} diff --git a/wait/timeout/timeout.test.ts b/wait/timeout/timeout.test.ts new file mode 100644 index 00000000000..f223e65c63d --- /dev/null +++ b/wait/timeout/timeout.test.ts @@ -0,0 +1,8 @@ +namespace $.$$ { + + $mol_test_mocks.push( $ => { + $.$mol_wait_rest = function $mol_wait_rest_mock( this: $ ) { } + $.$mol_wait_rest_async = async function $mol_wait_rest_async_mock( this: $ ) {} + } ) + +} diff --git a/wait/timeout/timeout.ts b/wait/timeout/timeout.ts index e5abf2e1ffd..64ecdfcfd2e 100644 --- a/wait/timeout/timeout.ts +++ b/wait/timeout/timeout.ts @@ -1,6 +1,6 @@ namespace $ { - export function $mol_wait_timeout_async( this: $, timeout: number ) { + export function $mol_wait_timeout_async( this: $, timeout: number ): Promise< void > { const promise = $mol_promise() const task = new this.$mol_after_timeout( timeout , ()=> promise.done() ) return Object.assign( promise, { diff --git a/wire/async/async.test.ts b/wire/async/async.test.ts index 86cf4fec124..a43a6a719d2 100644 --- a/wire/async/async.test.ts +++ b/wire/async/async.test.ts @@ -25,7 +25,7 @@ namespace $ { static send( next: string ) { $mol_wire_sync( this.first ).push( next ) - this.$.$mol_wait_timeout(0) + $$.$mol_wait_timeout(0) this.last.push( next ) } @@ -39,8 +39,8 @@ namespace $ { $.$mol_after_mock_warp() await promise - $mol_assert_like( NameLogger.first, [ 'john', 'jin' ] ) - $mol_assert_like( NameLogger.last, [ 'jin' ] ) + $mol_assert_equal( NameLogger.first, [ 'john', 'jin' ] ) + $mol_assert_equal( NameLogger.last, [ 'jin' ] ) }, @@ -51,7 +51,7 @@ namespace $ { function send_name( next: string ) { $mol_wire_sync( first ).push( next ) - $.$mol_wait_timeout(0) + $$.$mol_wait_timeout(0) last.push( next ) } @@ -63,8 +63,8 @@ namespace $ { $.$mol_after_mock_warp() await promise - $mol_assert_like( first, [ 'john', 'jin' ] ) - $mol_assert_like( last, [ 'jin' ] ) + $mol_assert_equal( first, [ 'john', 'jin' ] ) + $mol_assert_equal( last, [ 'jin' ] ) },